初始化列表和特殊成员
2026/6/9 12:11:02 网站建设 项目流程

一 首先要知道,是先执行初始化列表,然后在执行构造函数体

#include<iostream> using namespace std; class Date { public: int m_year; int m_month; int m_day; public: Date() { m_year = 0; m_month = 0; m_day = 0; } Date(int year, int month, int day) { m_year = year; m_month = month; m_day = day; } }; class MM { private: int m_age; Date m_brith; public: MM() { } MM(int age, const Date& brith) { m_age = age; m_brith = brith; } //MM(int year, int month, int day) //{ // m_age = 2025 - year; // m_brith=Date(year, month, day);//m_brith(year,month,day)写法错误 //} //除了上面的方式,还可以通过初始化列表的方式来初始化对象参数 MM(int year, int month, int day) :m_brith(year,month,day) ,m_age(2025-year) { } void show() { cout << m_age <<" "<< m_brith.m_year<<" " << m_brith.m_month<<" " << m_brith.m_day << endl; } }; int main() { MM mm(21, Date(2004, 3, 10)); mm.show(); MM mm1(2004, 3, 10); mm1.show(); MM nullmm; return 0; }

当我创建对象nullmm的时候,会调用MM类对成员变量进行初始化,因为m_age的类型是int型,即使不初始化,系统会给他分配一个随机值,然后开始初始化Date m_brith。

这时候会调用成员对象m_brith的构造函数对成员变量进行初始化,因为在创建对象的时候没有带任何参数,所以会调用无参的构造函数来对成员变量进行初始化。

int main() { MM mm(21, Date(2004, 3, 10)); mm.show(); MM mm1(2004, 3, 10); mm1.show(); MM nullmm; return 0; }
MM() { } MM(int age, const Date& brith) { m_age = age; m_brith = brith; } MM(int year, int month, int day) { m_age = 2025 - year; m_brith=Date(year, month, day);//m_brith(year,month,day)写法错误 }

为啥都会报错?????

1.当调用MM mm(21,Date(2004,3,10)),会调用构造函数Date(int age,const Date&brith),然后开始初始化成员变量,m_age是int型,会被初始化随机值,然后开始初始化m_brith。m_brith是Date类的成员对象,就会调用Date类的构造函数对成员变量进行初始化,因为带参的构造函数没有提供初始值,所以不会调用Date类的带参构造函数,因为存在构造函数,所以系统不会提供带参构造函数。然后对于m_brith的初始化就不能初始。所以系统报错。

关键理解就是对于成员对象,必须先初始化,然后在赋值。

2 比如调用MM mm(21,Date(2004,3,10)的时候,Date(2004,3,10)并不是成员对象m_brith对成员变量进行初始化,而是初始化之后的赋值。这时候的意思就是创建一个临时对象,等初始化之后,在赋值给m_brith。

MM() :m_brith(2004, 3, 10) { } MM(int age, const Date& brith) :m_age(age) ,m_brith(brith) { } MM(int year, int month, int day) :m_brith(year,month,day) ,m_age(2025-year) { }

如果我在这时候把Date()无参构造函数注释掉,就会报错,那这时候我怎么修改代码可以避免报错呢

答案就是初始化参数列表

另外在C++中,如果一个类给了构造函数,不管是无参还是带参的,这时候系统都不会自动给一个默认构造函数了。

二 explicit 抑制构造函数的隐式转换

class Int { public: int number; explicit Int(int number) :number(number) {} }; int main() { Int num = 22;//隐式调用 //如果不想要隐式调用,可以加一个explicit Int num1 = Int(23);//先初始化num1,然后创建一个临时对象,赋值给num1 Int num2(24);//显示调用,先创建对象num1,然后在初始化number return 0; }

三 default 告诉编译器使用默认的构造函数和析构函数(只能是无参的构造函数和析构函数)

Int() =default;

四 delete 禁止构造函数和赋值运算符

class Int { public: int number; Int()=default; Int(const Int& other) = delete; Int(int number) :number(number) {} }; int main() { Int k = m; return 0; }

这里调用不了拷贝构造函数,因为已经删了。

还有一个重点,就是即使写了构造函数,如果没有拷贝构造函数,编译器也会写一个拷贝构造函数

四 特殊成员

(一)static

//static静态成员变量 //1.在类中只是声明,没有分配内存空间,所以还不能使用 //2.必须在类外定义或者通过C++17的内联解决 //static静态成员函数 在静态成员函数里面,只能访问静态成员变量。 class Student { public: int m_age; string m_name; //static int m_count; 无法解析的外部符号 "public: static int Student::m_count" (? m_count@Student@@2HA) //这个只是声明,不是定义,还没有分配内存空间,所以不能使用 static int m_count;//通过静态成员变量,成功的计算出班级里有多少学生 inline static int m_count1; Student() { m_count++; m_count1++; } Student(int age, const string& name) :m_age(age) ,m_name(name) { m_count++; m_count1++; } void show() { cout << m_age << " " << m_name << endl; } }; int Student::m_count = 0; int main() { Student s1(21, "lzh"); s1.show(); Student s2; Student s3; //静态变量可以通过对象访问 cout << s3.m_count <<" "<<s3.m_count1 << endl; //静态变量也可以通过类名直接访问 cout << Student::m_count << " " << Student::m_count1 << endl; return 0; }

(二)const

1.const成员变量:只能通过初始化列表修改初始值

2.const成员函数:不能修改成员变量(如果要修改成员变量的值,可以在成员变量定义的地方加上mutable)

3 常对象只能调用常函数

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询