C++基础知识面试必备、复习细节 (2)
类基础知识
- c语言强调面向过程,c++强调面向对象
- 定义public说明符之后的成员在整个程序内可被访问;定义private说明符之后的成员只可以被类的成员函数访问,即隐藏了实现细节;定义protected说明符则说明该类或该类的子类、友元可以访问
- 使用struct和class定义类的唯一区别在于默认的访问权限不一样,struct的默认访问权限为public,class的默认访问权限为private
- 封装的优点:确保用户代码不会无意破坏封装对象的状态,且被封装类的具体实现可以在不影响用户代码的前提下完成修改
- sizeof一个空类的结果是1,如果有虚函数则会增加一个虚函数指针的大小,静态类数据成员不影响类大小,类成员的大小只受其变量的影响,函数存储在公共代码区
- 类中成员函数使用名字顺序:优先在成员函数中查找该名字声明,如果没有找到再去类中查找,因此如果形参的变量名和类的变量名相同则默认为形参的,访问类的变量可以用this指针访问
- this指针:指向当前类对象,是一个 * const
- 继承是"is a"关系,组合是"has a"关系
构造函数和析构函数
-
构造函数为类分配内存和初始化,析构函数则是释放内存
-
构造函数和析构函数不返回任何类型
-
构造函数可以被多次重载,参数列表不同即可
-
构造函数可以通过在函数参数列表后加上初始化器更方便地进行初始化
-
默认的拷贝构造函数只是进行成员变量的简单赋值,因此如果有内存分配则需要自己重新定义拷贝构造函数
-
如果有自己进行内存分配,则需要自己写析构函数
-
构造时从上到下:类先调用父类的构造函数再调用子类的构造函数;
析构时从下到上:类先调用子类的析构函数再调用父类的析构函数;
-
如果没有显式定义构造函数和析构函数,系统会隐式构造默认构造函数。只有类没有声明任何构造函数时系统才会生成默认构造函数
-
派生类构造函数名(总参数列表) : 父类构造函数名(参数列表) //如果不调用父类构造函数,则使用默认构造函数
拷贝控制
-
拷贝构造函数的参数是自身对象类型的引用(必须是引用,否则岂不是永远陷入了拷贝的无限循环)
-
可以通过重载赋值运算符’='实现赋值拷贝
-
通常,拷贝函数的调用时机为:函数的参数为类的对象或函数的返回值是类的对象时
-
拷贝分为浅拷贝和深拷贝:
-
浅拷贝:按字节拷贝。这在一些情况会产生问题:如果要拷贝的类中有指针变量或数组之类的,则按字节拷贝会直接按字节进行拷贝,因此就会出现两个指针指向同一内存的情况,当一个类析构时会释放内存,则另一个指针将指向一个未知区域,造成内存泄露,数组也是同理,当一个类析构时会释放内存,则造成了内存泄漏,因此如果有指针或者数组之类变量,需要采用深拷贝。
-
深拷贝:每个对象共同拥有自己的资源,必须显式提供拷贝构造函数和赋值运算符。
深拷贝在拷贝数组或指针时将重新开辟新的区域进行存储然后拷贝值
-
浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
-
如果要对指针变量进行浅拷贝,可以采用 std::shared_ptr 解决该问题
-
友元
-
友元函数:在类中,用在外部函数申明前加关键字friend,可以允许这个外部访问本类protected 和 private 的成员。友元函数不是类成员函数,是类外的函数,但是可以访问所有成员
class Point{ public: friend void fun(Point t);//友元函数 private: int a; protected: int b; }; void fun(Point t) { t.a = 100; t.b = 2000; cout << t.a << " " << t.b << endl