一、在C++中对象是如何组合的
1.问题的引入----在C++中我们如何将对象成员进行初始化
首先要明确的是你真的能够分清楚什么是赋值,什么又是初始化么?
初始化与赋值不同
初始化是用已存在的对象或值对正在创建的对象进行初值设置
赋值是用已存在的对象或值对已经存在的对象进行值设置
区别:
初始化: 被初始化的对象正在创建
赋值: 被赋值的对象已经存在
2.所以我们就能够明白一点 :构造函数体部分只是对我们的变量进行赋值 并非是我们通常所说的初始化
那么这时候我们需要思考,C++中真正意义上的初始化是怎么做的呢?
3.初始化列表的引入---初始化变量
可以说初始化列表的引入恰恰满足了我们对变量初始化的需要,下面举例说明。
example1.cpp
#include <iostream>
using namespace std;
class Test
{
private:
int mI;
public:
Test(int i)
{
cout<<"mI = %d"<<mI<<endl;
mI = i;
}
int GetI()
{
return mI;
}
};
class M
{
private:
const int mJ; //定义常量,但是没有初始化!!!
Test M1; //定义了一个类成员,这样做可行么?
Test M2;
public:
M()
{
cout<<"M() \n"<<endl;
}
};
int main()
{
M m1;
return 0;
}
上面的例子在gcc环境下编译的时候会提示如下问题
9_1.cpp: In constructor ‘M::M()’:
9_1.cpp:27: error: uninitialized member ‘M::mJ’ with ‘const’ type ‘const int’
9_1.cpp:28: error: no matching function for call to ‘Test::Test()’
9_1.cpp:10: note: candidates are: Test::Test(int)
9_1.cpp:6: note: Test::Test(const Test&)
9_1.cpp:28: error: no matching function for call to ‘Test::Test()’
9_1.cpp:10: note: candidates are: Test::Test(int)
9_1.cpp:6: note: Test::Test(const Test&)
意思是说我们声明变量mJ,M1,M2的时候没有对它进行初始化,当然会出错的。
所以我们修改成下面的程序,用初始化列表进行初始化就行了
#include <iostream>
using namespace std;
class Test
{
private:
int mI;
public:
Test(int i)
{
mI = i;
cout<<"mI = "<<mI<<endl;
}
int GetI()
{
return mI;
}
};
class M
{
private:
const int mJ;
Test M1;
Test M2;
public:
M():mJ(1),M1(2),M2(3)
{
cout<<"M() \n"<<endl;
}
};
int main()
{
M m1;
return 0;
}
当让值得注意的就是:
1.成员变量的初始化顺序与声明的顺序相关,与在初始化列表中的顺序无关
2.初始化列表先于构造函数的函数体执行
二、所谓析构函数
C + +中的类可以定义一个特殊的成员函数清理对象,这个特殊的成员函数叫做析构函数。
定义:~ClassName()
析构函数没有参数也没有任何返回类型的声明
析构函数在对象销毁时自动被调用
注意:
构造函数与析构函数的调用秩序
1.当类中有成员变量是其它类的对象时,首先调用成员变量的构造函数调用顺序与声明顺序相同
2.后调用自身类的构造函数析构函数的调用秩序与对应的构造函数调用秩序相反
举例如下:
#include <iostream>
using namespace std;
class Test
{
private:
int mI;
public:
Test(int i)
{
mI = i;
cout<<"Test mI = "<<mI<<endl;
}
~Test()
{
cout<<"~Test : mI = "<<mI<<endl;
}
};
class M
{
private:
const int mm;
Test mI;
Test mJ;
public:
M():mm(0),mI(1),mJ(2)
{
cout<<"M() mm = "<<mm<<endl;
}
~M()
{
cout<<"~M mm = "<<mm<<endl;
}
};
int main()
{
M m1;
M m2;
return 0;
}
仔细分析会得出如下结果:
Test mI = 1
Test mI = 2
M() mm = 0
Test mI = 1
Test mI = 2
M() mm = 0
~M mm = 0
~Test : mI = 2
~Test : mI = 1
~M mm = 0
~Test : mI = 2
~Test : mI = 1