- 构造函数
- 析构函数
- 赋值函数
A() //默认构造函数
A(const A &) //默认拷贝构造函数
~A() //析构函数
A & operator=(const A& a ) //复制拷贝构造韩胡说
初始化列表
http://www.cnblogs.com/graphics/archive/2010/07/04/1770900.html
http://blog.csdn.net/zlb_xidian/article/details/5782341
class foo
{
string name ;
int id ;
foo(string s, int i):name(s), id(i){} ; // 初始化列表
};
- 初始化阶段和计算阶段,初始化阶段先于计算阶段。
- 初始化阶段:所有类类型(class type)的成员都会在初始化阶段初始化,即使该成员没有出现在构造函数的初始化列表中。
- 计算阶段:执行构造函数体内的赋值操作,
//计算阶段
class Test1
{
Test1() // 无参构造函数
{
cout << "Construct Test1" << endl ;
}
Test1(const Test1& t1) // 拷贝构造函数
{
cout << "Copy constructor for Test1" << endl ;
this->a = t1.a ;
}
Test1& operator = (const Test1& t1) // 赋值运算符
{
cout << "assignment for Test1" << endl ;
this->a = t1.a ;
return *this;
}
int a ;
};
class Test2
{
Test1 test1 ;
Test2(Test1 &t1)
{
test1 = t1 ;
}
};
Test1 t1 ;
Test2 t2(t1) ;
- 输出结果是
Construct Test1
Construct Test1
assignment for Test1
- 第一行输出对应调用代码中第一行,构造一个Test1对象
- 第二行输出对应Test2构造函数中的代码,用默认的构造函数初始化对象test1,这就是所谓的初始化阶段。
- 第三行输出对应Test1的赋值运算符,对test1执行赋值操作,这就是所谓的计算阶段。
- 初始化两者方式:一是使用初始化列表,二是在构造函数体内进行赋值操作。
必须放在初始化列表中
- 类存在派生的关系,派生类可以直接在初始化列表中调用基类的特定构造函数以向他传递参数
class A
{
public:
A(int x);
};
class B :public A
{
B(int x,int y );
};
B::B(int x,int y):A(x) // 初始化类别里调用A的构造函数
- 初始化const修饰的类成员或初始化引用成员数据;
- 对于类成员是const修饰,或是引用类型的情况,是不允许赋值操作的,(显然嘛,const就是防止被错误赋值的,引用类型必须定义赋值在一起)因此只能用初始化列表对齐进行初始化。
#include <stdio.h>
class base
{
private:
const int a;
int& b;
public:
// base(int m, int n)
// {
// a = m;
// b = n;
// }
base(int m, int n):a(m),b(n)
{}
};
void main()
{
base ba(1,2);
}
- 类的成员的初始化可以采用初始化列表和函数体内赋值两者方法
class A
{
A(void); //默认构造函数
A(const A&other) //拷贝构造函数
A &opertor=(const A &other) //赋值函数
};
class B
{
public:
B(const A&a);
private:
A m_a;
};
//初始化列表初始化
B::B(const A& a):m_a(a)
{}
//函数体赋值初始化
B::B(const A& a)
{
m_a=a;
}
- 初始化列表:调用A的拷贝构造函数
- 赋值方式初始化m_a, 再调用类A的赋值函数,最好才将a赋给m_a
- 第一种效率高
对象的构造和析构顺序
- 析构函数按照和构造函数相反的顺序执行
- 数据成员按照其声明的顺序初始化