c语言重难点归纳(C基础知识总结)
c语言重难点归纳(C基础知识总结)1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;但无论哪种继承方式,上面两点都没有改变:1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public protected private2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected protected private3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private private private
公有成员在程序中类的外部是可访问的
私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的。
继承中的特点有public protected private三种继承方式,它们相应地改变了基类成员的访问属性。
1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public protected private
2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected protected private
3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private private private
但无论哪种继承方式,上面两点都没有改变:
1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
2.protected 成员可以被派生类访问。
如果您没有使用任何访问修饰符,类的成员将被假定为私有成员:
构造函数在每次创建类的新对象时执行,会返回任何类型,也不会返回 void,可用于为某些成员变量设置初始值。
无参数类外定义:Line::Line(void)
带参数:Line::Line( double len) 创建对象:Line line(10.0);
初始化列表来初始化字段:
Line::Line( double len): length(len) C::C( double a double b double c): X(a) Y(b) Z(c) //a b c 分别赋值给类中的成员变量X Y Z 析构函数
在每次删除所创建的对象时执行 不会返回任何值,也不能带有任何参数 有助于在跳出程序(比如关闭文件、释放内存等)前释放资源
Line::~Line(void)
拷贝构造函数通过使用另一个同类型的对象来初始化新创建的对象。
复制对象把它作为参数传递给函数。
复制对象,并从函数返回这个对象。
Line( const Line &obj); Line line2 = line1;调用拷贝构造函数。
直接初始化,调用构造函数 拷贝初始化,调用拷贝构造函数
友元函数定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。friend void printWidth( Box box );
友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。friend class ClassTwo;
定义时 :void printWidth( Box box ) { } 不是任何类的成员函数
内联函数在类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。
如果已定义的函数多于一行,编译器会忽略 inline 限定符。
this 指针是所有成员函数的隐含参数
友元函数没有 this 指针,因为友元不是类的成员
类的静态成员无论创建多少个类的对象,静态成员都只有一个副本。
不能把静态成员的初始化放置在类的定义中,可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化 int Box::objectCount = 0;
静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
继承一个类可以派生自多个类,多继承即一个子类可以有多个父类,它继承了多个父类的特性。class <派生类名>:<继承方式1><基类名1> <继承方式2><基类名2> …
一个派生类继承了所有的基类方法,但下列情况除外:基类的构造函数、析构函数和拷贝构造函数。基类的重载运算符。基类的友元函数。
重载运算符和重载函数同名函数的形式参数(指参数的个数、类型或者顺序)必须不同
重载的运算符是带有特殊名称的函数
Box operator (const Box& b) Box3 = Box1 Box2;
内存布局 https://blog.csdn.net/qq_36129744/article/details/60778907
多态虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
根据调用函数的对象的类型来执行不同的函数,
多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。
同名函数,基类中定义为虚函数,若把派生类的对象指针赋值给基类类型的指针,用这个基类指针调用函数时回去调用各自派生类中的同名函数
纯虚函数 virtual int area() = 0; 为了在基类中让中的虚函数没有具体实现。= 0 告诉编译器,函数没有主体
核心理念就是通过基类访问派生类定义的函数
析构函数应当是虚函数,将调用相应对象类型的析构函数,因此,如果指针指向的是子类对象,将调用子类的析构函数,然后自动调用基类的析构函数。
友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调用虚拟成员函数来解决友元的虚拟问题。
接口(抽象类 通常称为 ABC)至少有一个函数被声明为纯虚函数,则这个类就是抽象类
是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象,它只能作为接口使用。
一个 ABC 的子类需要被实例化,则必须实现每个虚函数
抽象基类为所有的外部应用程序提供一个适当的、通用的、标准化的接口。然后,派生类通过继承抽象基类,就把所有类似的操作都继承下来。
文件和流ofstream ifstream fstream
ios::app 追加模式。所有写入都追加到文件末尾。
ios::ate 文件打开后定位到文件末尾。
ios::in 打开文件用于读取。
ios::out 打开文件用于写入。
ios::trunc 如果该文件已经存在,其内容将在打开文件之前被截断,即把文件长度设为 0。
void open(const char *filename ios::openmode mode); f.open(name,ios::mode);
o和i都是相对于当前程序,程序在向外就是o即向文件流写入,i从文件流读取。
ifstream f; f是定义的一个ifstream类型的对象所以关闭文件流时用 f.close();
istream 的 seekg("seek get")和关于 ostream 的 seekp("seek put")
ios::beg(默认的,从流的开头开始定位),也可以是 ios::cur(从流的当前位置开始定位),也可以是 ios::end(从流的末尾开始定位)
// 定位到 fileObject 的第 n 个字节(假设是 ios::beg)
fileObject.seekg( n );
// 把文件的读指针从 fileObject 当前位置向后移 n 个字节
fileObject.seekg( n ios::cur );
// 把文件的读指针从 fileObject 末尾往回移 n 个字节
fileObject.seekg( n ios::end );
// 定位到 fileObject 的末尾
fileObject.seekg( 0 ios::end ); 异常处理
用 throw 语句在代码块中的任何地方抛出异常
try{这里或者这里调用的函数throw出异常}catch( ExceptionName e1 ){}catch( ExceptionName e2 ){}catch( ExceptionName eN ){}
catch(...) 处理 try 块抛出的任何类型的异常
catch (const char* msg)
定义新的异常:struct MyException : public exception
{const char * what () const throw (){return "C Exception";}}; try{throw MyException();}catch(MyException& e){std::cout << "MyException caught" << std::endl;std::cout << e.what() << std::endl;}
const throw() 不是函数,这个东西叫异常规格说明,表示 what 函数可以抛出异常的类型,类型说明放到 () 里,这里面没有类型,就是声明这个函数不抛出异常,通常函数不写后面的就表示函数可以抛出任何类型的异常。
动态内存new data-type;内置的数据类型,也可以是包括类或结构在内的用户自定义的任何数据类型。new 不只是分配了内存,它还创建了对象。
delete pvalue; pvalue = new char[20]; delete [] pvalue; 二维数组:array = new int *[m]; for( int i=0; i<m; i ){array[i] = new int [n] ;}for( int i=0; i<m; i ){delete [] arrar[i];}delete [] array; 命名空间
namespace namespace_name {代码声明} using namespace std;后续的代码将使用指定的命名空间中的名称
using std::cout;指定命名空间中的特定项目,只打算使用 std 命名空间中的 cout 部分,随后的代码中,在使用 cout 时就可以不用加上命名空间名称作为前缀,但是 std 命名空间中的其他项目仍然需要加上命名空间名称作为前缀
一个命名空间的各个组成部分可以分散在多个文件中。
命名空间可以嵌套:using namespace namespace_name1::namespace_name2; 模板
模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。
声明一个int向量以替代一维的数组:vector <int> a;(等于声明了一个int数组a[] 大小没有指定 可以动态的向里面添加删除)。二维vector <int *> a;三维vector <int**>a;
信号处理void (*signal (int sig void (*func)(int)))(int);
// 注册信号 SIGINT 和信号处理程序
signal(SIGINT signalHandler);
定义信号处理函数
void signalHandler( int signum ){exit(signum);}
raise() 生成信号,原型int raise (signal sig);
sleep(时间)在windows下是以毫秒为单位,而Linux是以秒为单位。
多线程POSIX 线程 pthread_create (thread类型为pthread_t的指向线程标识符指针 attr start_routine函数名即函数的起始地址 arg指向参数的通用指针) 无参数 ret = pthread_create(&tids[i] NULL say_hello NULL);通过结构传递多个参数
pthread_exit (status) pthread_join使一个线程等待另一个线程结束。代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。