#include<iostream> using namespace std; class Date { public: Date(int a, int b) { _b = b; _a = a; } private: int _a; const int _b; }; int main(void) { return 0; }
这段代码是存在问题的,const修饰的成员变量是不能在构造函数内初始化的,需要借助初始化列表
#include<iostream> using namespace std; class Date { public: //初始化列表:对象的成员定义的位置 Date(int a, int b) :_b(b) { _a = a; } private: //都是申明 int _a; const int _b; }; int main(void) { return 0; }
初始化列表:对象的成员定义的位置
class A { public: A(int a) :_a(10) { cout << "A()" << endl; } private: int _a; }; class Date { public: Date(int a=10, int b=11) :_b(b) { cout << "B()" << endl; _a = a; } private: int _a; const int _b; A aa1; };
编译器会报错,因为在Date类当中含有自定义类型的变量,自定义类型的变量会自动调用它的默认构造函数,如果没有默认构造函数就会导致编译无法通过:
错误 C2512 “A”: 没有合适的默认构造函数可用 2023_6_24 D:\CODE\2023_6_24\test.cpp 21
错误(活动) E0291 类 "A" 不存在默认构造函数 2023_6_24 D:\CODE\2023_6_24\test.cpp 21
默认构造函数就是不传参也可以调用的构造函数
class A { public: A() :_a(10) { cout << "A()" << endl; } private: int _a; }; class Date { public: Date(int a=10, int b=11) :_b(b) { cout << "B()" << endl; _a = a; } private: int _a; const int _b; A aa1; };
class A { public: A(int a=10) :_a(a) { cout << "A()" << endl; } private: int _a; }; class Date { public: Date(int a=10, int b=11) :_b(b) { cout << "B()" << endl; _a = a; } private: int _a; const int _b; A aa1; };
class A { public: A(int a=10,int b=20) :_a(a) ,_b(b) { cout << "a=" << a << " b=" << b << endl; cout << "A()" << endl; } private: int _a; int _b; }; class Date { public: Date(int a=10, int b=11) :_b(b) ,aa1(123,456) { cout << "B()" << endl; _a = a; } private: int _a; const int _b; A aa1; };
上述为正确的代码,那么既然初始化列表就可以完成构造函数,那为什么不只使用初始化列表呢?
比如以下的动态开辟二维数组的代码就能很好的解释这个问题
class AA { public: AA(int row = 10, int col = 5) :_row(row) ,_col(col) { _aa = (int**)malloc(sizeof(int*) * row); for (int i = 0; i < row; i++) { _aa[i] = (int*)malloc(sizeof(int) * col); } } private: int** _aa; int _row; int _col; };
临时变量具有常性
class AA { public: //AA(int row = 10, int col = 5) // :_row(row) // ,_col(col) //{ // _aa = (int**)malloc(sizeof(int*) * row); // for (int i = 0; i < row; i++) // { // _aa[i] = (int*)malloc(sizeof(int) * col); // } //} private: //int** _aa; //int _row; //int _col; int _a; }; int main(void) { Date d1; Date d2 = 3; Date& d3 = 5;//const类型转换到Date&类型,属于权限的放大,会报错 const Date& d4 = 6;//临时变量具有常性,加上const属于权限的平移 return 0; }
关键字:explicit
如果不想要发生上述的隐式类型转换,可以使用explicit来约束
class AA { public: //AA(int row = 10, int col = 5) // :_row(row) // ,_col(col) //{ // _aa = (int**)malloc(sizeof(int*) * row); // for (int i = 0; i < row; i++) // { // _aa[i] = (int*)malloc(sizeof(int) * col); // } //} private: //int** _aa; //int _row; //int _col; int _a; }; int main(void) { Date d1; Date d2 = 3; Date& d3 = 5; const Date& d4 = 6; return 0; }
这样代码就不会发生隐式类型转换了
设计一个类,在类外面只能在栈/堆上面创建对象
class A { public: A() :_a(10) {} private: int _a; }; int main(void) { static A aa1;//静态区 A aa2;//栈 A* ptr = new A;//堆 return 0; }
class A { public: static A GetStackObj() { A aa1; return aa1; } static A* GetHeapObj() { A* ptr = new A; return ptr; } private: A() :_a(10) {} private: int _a; }; int main(void) { //static A aa1;//静态区 //A aa2;//栈 //A* ptr = new A;//堆 A::GetHeapObj(); A::GetStackObj(); return 0; }
在单例设计模式当中会运用到