构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。
例如:
#include<iostream>
class Test
{
public:
Test(int a, int b) : mb(ma), ma(a), mc(ma)
{}
void Show()
{
std::cout << "ma:" << ma << std::endl;
std::cout << "mb:" << mb << std::endl;
std::cout << "mc:" << mc << std::endl;
}
private:
int ma;
int mb;
int mc;
};
int main()
{
Test test1(10,20);
test1.Show();
return 0;
}
结果为:
从结果中,我们可以看出,初始化的顺序和初始化列表的顺序无关,仅仅和声明有关。
需要初始化的数据成员是对象的情况:
1.数据成员是对象,并且这个对象只有含参数的构造函数,没有无参数的构造函数;
如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么他将无法完成第一步,就会报错
#include<iostream>
class Date
{
public:
Date(int y, int m, int d)
{
year = y;
month = m;
day = d;
}
public:
int year;
int month;
int day;
};
class Stu
{
public:
Stu(char* name, int id, int age, int y, int m, int d):
birth(y, m, d)//调用birth对象中,带有三个参数的构造函数,对其初始化
{
mname = new char[strlen(name) + 1];
strcpy(mname, name);
mid = id;
mage = age;
birth = Date(y, m, d);//调用赋值运算符重载函数
}
void show()
{
std::cout<< mname<<std::endl;
std::cout<< mid<<std::endl;
std::cout<< mage<<std::endl;
std::cout<< birth.year<<std::endl;
std::cout<< birth.month<<std::endl;
std::cout<< birth.day<<std::endl;
}
private:
char* mname;
int mid;
int mage;
Date birth;//成员对象
};
int main()
{
Stu stu1("zhangsan", 1, 20, 1998, 12, 12);
stu1.show();
return 0;
}
2.对象引用或者cosnt修饰的数据成员
当类成员中含有一个const对象时,或者是一个引用时,他们也必须要通过成员初始化列表进行初始化,因为这两种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。
例子:
class Test
{
priate:
const int a; //const成员声明
public:
Test():a(10){} //初始化
};
或
class Test
{
private:
int &a; //声明
public:
Test(int a):a(a){} //初始化
}
static修饰成员变量:
不属于对象独享,属于对象共享,在类外要初始化,不依赖对象的访问
#include<iostream>
class Test
{
public:
Test(int a, int b)
{
mb = b;
}
void Show()
{
std::cout << "ma:" << ma << std::endl;
std::cout << "mb:" << mb << std::endl;
}
public:
static int ma;//修饰静态成员变量
int mb;
};
int Test::ma = 100;//在类外初始化
int main()
{
Test test1(10, 20);
std::cout << sizeof(Test) << std::endl;
std::cout << test1.mb << std::endl;
std::cout << Test::ma << std::endl;//不依赖对象访问
std::cout << test1.ma << std::endl;
test1.Show();
return 0;
}
static修饰成员方法:
如果static修饰成员方法,则是 _cdel调用约定,没有this指针;
不能访问普通成员变量,只能访问静态成员变量和全局变量;
静态成员方法不能调用普通成员方法,但是普通成员方法可以调用静态的成员方法。
#include<iostream>
int gdata = 10;//全局变量
class Test
{
public:
Test(int a, int b)
{
mb = b;
}
static void Show()//_cdecl调用约定,没有this指针
{
std::cout << "ma:" << ma << std::endl;
//std::cout << "mb:" << mb << std::endl;//错误,不能调用普通成员变量
std::cout << "mb:" << gdata << std::endl;//正确,可以调用全局变量
//Print();//错误,不能调用普通成员方法
}
void Print()//thiscall this Test* const this
{
std::cout << "ma:" << ma << std::endl;
std::cout << "mb:" << mb << std::endl;
std::cout << "mb:" << gdata << std::endl;
Show();//可以调用静态成员变量和方法
}
public:
static int ma;
int mb;
};
int Test::ma = 100;
int main()
{
Test test1(10, 20);
std::cout << test1.mb << std::endl;
std::cout << Test::ma << std::endl;
std::cout << test1.ma << std::endl;////不依赖与对象访问
Test::Show();//不依赖与对象访问
test1.Show();
return 0;
}
常对象和常方法
1.常对象不能调用普通方法
2.常对象能调用常方法
3.普通对象可以调用常方法
4.普通函数可以调用常方法
5.常函数不能调用普通方法
6.常成员变量,一定要初始化(构造函数的初始化列表中);
#include<iostream>
class Test
{
public:
Test(int a, int b) : mb(b), ma(a)//this Test* const
{}
//void Show()//错误,常对象不能调用普通方法
void Show() const// Test* const this const
{
//.Print();//错误,常函数不能调用普通函数
std::cout << "ma:" << ma << std::endl;
std::cout << "mb:" << mb << std::endl;
}
void Print()// Test* const this
{
std::cout << "hello world !" << std::endl;
Show();//正确,普通函数可以调用常函数
}
private:
int ma;
int mb;
};
int main()
{
Test test1(10, 20);
test1.Show();//正确,普通对象可以调用常方法 Test* ==> Test* const
const Test test2(30, 40);
test2.Show();//正确,常对象可以调用常方法const Test* ==> Test* const
//test2.Print();错误,常对象不能调用普通方法
return 0;
}