学习C++中 . . .
近期在复盘学习C++相关的基础知识,抽空将自己学习过程中整理的要点记录下来,以便后续学习过程进行回顾复盘
用于初始化类数据
- 默认构造函数
- 拷贝构造函数
- 赋值构造函数
构造函数的拷贝
-
未自定义拷贝构造函数时,会自动生成一个“合成拷贝构造函数”
缺点:浅拷贝,如果存在指针类型的拷贝数据,那么就会出错;
-
自定义拷贝构造函数(深层拷贝)
优点:在对指针进行拷贝时,可以给它独立分配出内存空间,以防止拷贝后的指针指向原来指针同一个所指向的内存;
// 拷贝时为其独立分配内存空间,那么原参数更改后保证修改前的拷贝部分不改变 addr = new char[64]; // 分配空间 strcpy_s(addr, 64, man.addr);
什么时候调用拷贝构造函数
-
1、调用函数时,实参是一个对象,而形参不是引用类型;
-
2、函数返回类型是类,并且没有定义成引用类型;
Human getBetterman(const Human& man1, const Human& man2) { // 若此处形参没有加&,那么在传参过程中 if (man1.getSalary() > man2.getSalary()) { // 也会调用拷贝构造函数 return man1; } else { return man2; // 此函数返回类型为类,那么在返回过程中将会调用拷贝构造函数 } }
-
3、对象数组的初始化列表;
Human h1, h2, h3, h4; Human F4 [4] = {h1, h2, h3, h4}; // 调用4次拷贝构造函数
定义引用类型参数:例如要传入一个参数为对象类型时,可以避免再创建出一个对象,降低运行成本;再加 const 以防止原来数据发生改变
赋值构造函数
-
未定义复制构造函数时,系统会自动生成默认的赋值构造函数(default memberwise copy),即默认的成员逐一赋值操作;
-
自定义赋值构造函数
析构函数
- 不能主动调用,对象销毁时系统自动调用;
- 在类运行结束后,用于释放内存;(例如构造函数时分配了独立内存,那么就需要析构函数进行内存释放)
- 如果构造函数中没有申请新的内存资源,那么一般不会调用析构函数;
- 如果不定义,编译器会生成的默认析构函数(什么也不做);
const 成员函数
保证函数内部不会修改任意数据成员,否则可能使得const 类型参数被修改,因此在成员函数身上标注 const;
-
const 只能作用于 const 变量数据;
class Boy { public: void play const ( ) { } // 此处函数也定义为 const 类型 ... } int main { const Boy jack; // jack 已经被定义成了 const 对象 jack.play( ) ; // 此处 play()函数应该也是 const 函数,否则出现类型不兼容 }
this 指针
在被调用的成员函数内部用来指向其调用者(一个对象);
【工作过程】编译器自动将 this 指针加到每一个 member function 的参数列表;
// 原函数定义形式 Human& Human::copy( const Human &man) { } // 编译器转换后结果 Human& Human::copy(Human *this, const Human &man) // 增加了对象的 this 指针
-
若想要实现对象的复制,最好先确定两个对象是否相同,这也要用到 this 指针;
Human& Human::copy(const Human &man) { if (this != &man) { } }
静态类成员 static
将成员与任意类对象独立开来;
static data member 用来表示唯一的、可共享的 member ,意味着无论创建多少个同一类的对象,静态成员都只有一个实体,可共享;
- 【声明定义】1. 类中 private 进行声明;2. 类的实现代码文件中进行初始化;(如果是 const 类型也可以在类中声明时进行初始化,但只能初始化一次);
- 【调用】对象的所有成员函数(静态或非静态)都可以访问静态类成员(可读可写);但类不能直接访问;
- 可理解为所有类中的“全局变量”,即不为某一个类所独有;
静态成员函数 static Member Function
将函数与对象独立开来;属于整个类
实现“与任何对象都无瓜葛”的情形下被调用
- 【区别于一般成员函数】无 this 指针,只能访问静态数据成员(static data member);而·一般成员函数通过储存在每个对象中的 this 指针,才能访问储存于每个对象中的非静态数据成员(non-static data member);
- 【使用】类可以调用,普通对象也可以调用;
友元
【作用】使得类可以允许其他类 (友元类) 或者函数 (友元函数) 访问它的非公有成员**,令其成为它的友元 (friend)
- 【使用】加 friend 关键字;
- 【位置】class 定义内部中的任意位置,不受 private 和 public 影响。一般最好在类定义的开始或结束前集中声明友元;
- 【不一定非用友元】友元的建立,通常是为了效率。如果只希望某个数据成员的读取和写入,那也可以为它提供具有 public 访问权限的 inline 函数。就是建立友元的另一个替代方案。
封装的益处
将数据成员定义成 private,就可以自由的修改数据,只要类的接口不变,用户代码就无需改变;但如果是 public ,改变后所有使用原数据成员的代码都要发生变化。除此之外,定义 private 能防止由于用户的原因造成数据被破坏。
- 确保用户代码不会无意之间破坏封装对象的状态;
- 被封装的类的具体实现细节可以随时改变,而无需调整用户级别的代码;