C++笔记4.21

知识点1 类的空间大小

  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class Data  
  6. {  
  7. private:  
  8.     int num;//成员数据占一个类的空间大小,4B  
  9. public:  
  10.     //成员函数不占据空间大小  
  11.     void setNum(int data)  
  12.     {  
  13.         num = data;  
  14.     }  
  15.   
  16.     int getNum(void)  
  17.     {  
  18.         return num;  
  19.     }  
  20. };  
  21.   
  22. int main()  
  23. {  
  24.     printf ("%d\n",sizeof(Data));  
  25. }  

知识点2 在类的内声明类外定义成员函数

使用作用域符号::

  1. class Data  
  2. {  
  3. private:  
  4.     int num;  
  5. public:  
  6.     void setNum(int data);  
  7.   
  8.     int getNum(void);  
  9.   
  10. };  
  11.   
  12. void Data::setNum(int data)  
  13. {  
  14.     num = data;  
  15. }  
  16.   
  17. int Data::getNum(void)  
  18. {  
  19.     return num;  
  20. }  

知识点3 类的定义在头文件,成员函数在cpp中实现

分别写代码

头文件data.h

  1. #ifndef DATA_H  
  2. #define DATA_H  
  3.   
  4.   
  5. class data  
  6. {  
  7.     public:  
  8.         data();  
  9.         virtual ~data();  
  10.         void numSet(int n);  
  11.         int numGet(void);  
  12.   
  13.     protected:  
  14.   
  15.     private:  
  16.         int num;  
  17. };  
  18.   
  19. #endif // DATA_H  

存放函数定义文件data.cpp

  1. #include "data.h"  
  2.   
  3. data::data()  
  4. {  
  5.     //ctor  
  6. }  
  7.   
  8. data::~data()  
  9. {  
  10.     //dtor  
  11. }  
  12.   
  13. int data::numGet(void)  
  14. {  
  15.     return num;  
  16. }  
  17.   
  18. void data::numSet(int n)  
  19. {  
  20.     num = n;  
  21. }  

在主文件中使用main.cpp

  1. #include <iostream>  
  2. #include "data.h"  
  3.   
  4. using namespace std;  
  5.   
  6. int main()  
  7. {  
  8.     data ob;  
  9.     ob.numSet(200);  
  10.     cout << ob.numGet() << endl;  
  11. }  

知识点4 构造函数和析构函数的概述

构造函数和析构函数会被编译器自动调用,构造函数完成对象的初始化,析构函数在对象结束时候完成清理工作,构造函数可以重载但是析构函数一个类只能有一个。

构造函数:实例化对象的时候系统自动调用

析构函数:对象释放的时候系统自动调用

知识点5 析构函数的定义

构造函数的语法:构造函数的函数名和类名相同,没有返回类型,连void都不可以有,但是函数可以有参数,可以重载

析构函数的语法:函数名是在类名前面加~,没有返回类型,也不能添加void,不可以有参数,不能够重载

  1. class Data  
  2. {  
  3. private:  
  4.     int num;  
  5. public:  
  6.     Data()//无参构造函数  
  7.     {  
  8.         num = 0;  
  9.     }  
  10.       
  11.     Data(int n)//有参构造函数  
  12.     {  
  13.         num = n;  
  14.     }  
  15.       
  16.     ~Data()//析构函数  
  17.     {  
  18.         cout << "De constructor" << endl;  
  19.     }  
  20. };  

知识点6 构造函数的分类以及调用

按参数分类:分为无参构造函数和有参构造函数

按类型分类:分为普通构造函数和拷贝构造函数

在实例化类的时候调用构造函数,一个对象只会调用一种构造函数

  1. int main()  
  2. {  
  3.     Data ob1;//隐式调用默认(无参)构造  
  4.     Data ob2 = Data();//显式调用默认构造  
  5.     Data ob3(10);//隐式调用有参构造  
  6.     Data ob4 = Data(10);//显式调用有参构造  
  7.     Data ob5 = 30;//隐式转换  
  8.     Data(40);//匿名对象;当前语句结束后立即释放  
  9. }  

不能使用Data ob6()这种形式,编译器会视作一个函数的声明

拷贝构造函数使用旧对象给新对象赋值

定义方式

  1. Data (const Data &ob)  
  2. {  
  3.     num = ob.num;  
  4.     cout << "拷贝构造" << endl;  
  5. }  

使用方法

  1. Data ob1;  
  2. Data ob6;  
  3. ob6 = ob1;  

拷贝构造的注意事项

1 不能调用拷贝构造函数去初始化匿名对象

2 对象作为函数的参数,如果实参和形参都是普通对象就会调用拷贝构造

知识点7 构造函数的调用规则

系统会对任何一个类默认提供三个成员函数

默认构造函数(空)、默认析构函数(空)、默认拷贝构造函数(浅拷贝)

如果用户提供了有参构造系统的默认构造函数会被自动屏蔽,但是默认拷贝函数不会被屏蔽。

如果用户提供了拷贝构造函数,将屏蔽系统的默认构造函数和默认拷贝构造函数。

对于一个类,用户一半要实现无参构造、有参构造、拷贝构造、析构

知识点8 深拷贝和浅拷贝

如果类中的成员指向了堆区空间,一定要在析构函数中释放空间,默认的拷贝构造属于浅拷贝,不开辟空间,容易造成问题

知识点9 初始化列表

初始化成员列表(参数列表)这个方式只能在构造函数的时候使用

  1. Data (int a,int b,int c):m_a(a),m_b(b),m_c(c)  
  2. {  
  3.     //替代了原来这种构造方式  
  4.     //m_a = a;  
  5.     //m_b = b;  
  6.     //m_c = c;  
  7. }  

知识点10 类的对象作为另外一个类的成员

用类嵌套类的时候,想要用构造函数,必须保证成员对象的构造函数被调。构造函数的调用是发生在初始化的过程,无法在函数中写代码,当使用构造函数初始化一个对象,只能用初始化列表隐式地调用各自对象成员的自己的构造函数去实例化自己的对象成员。不然系统会默认调用对象成员的无参构造。使用初始化列表的方法才能够使对象成员调用有参构造,

调用顺序

对象成员的构造>>自己的构造函数>>析构自己>>析构对象成员

注意点

1 按各对象在类定义中的顺序(和参数列表本身的顺序 无关)依次调用他们的的构造函数

2 先调用对象成员的构造函数,再调用本身的构造函数。析构函数的调用顺序和构造函数相反。

知识点11 explicit关键字

C++提供了explicit的关键字从而禁止通过构造函数进行的隐式转换。声明为explicit的构造函数不能够在隐式转换中使用

知识点12 使用new和delete从堆区申请空间

和malloc calloc recalloc比较

malloc返回一个void指针,c++不允许将void值赋值给任何其他指针,必须进行强制转换。

malloc可能申请内存失败,必须使用返回值判断确保内存分配成功

malloc不会调用构造函数,free不会调用析构函数(在c++中使用时的根本问题)

发表评论

邮箱地址不会被公开。 必填项已用*标注