当定义或初始化一个类对象时,究竟会调用哪个呢?
1.当定义一个新的类对象时,会调用类的构造函数。
2.当初始化一个新的类对象时,会调用类的复制构造函数。
3.当给一个已存在的类对象赋值时,调用的是拷贝赋值操作符。
为了说明这一点,我们来看看下面的例子:
//头文件
#ifndef CONSTRUCTOR_H_
#define CONSTRUCTOR_H_
#include <iostream>
using namespace std;
class Test
{
public:
Test(int i=0,int j=0):x(i),y(j){cout<<"constructor running!"<<endl;}
Test(Test & t){x=t.x;y=t.y;cout<<"copy constructor running!"<<endl;}
operator=(Test &t){x=t.x;y=t.y;cout<<"operator = running!"<<endl;}
private:
int x;
int y;
};
#endif //CONSTRUCTOR_H_
在main函数中,当执行以下语句时:
1)
Test test1(0,0);
输出:constructor running!
2)
Test test1(0,0);
Test test2 = test1;
输出:constructor running!
copy constructor running!
3)
Test test1(0,0);
Test test3(test1);
输出:constructor running!
copy constructor running!
4)
Test test1(0,0);
Test test4;
test4 = test1;
输出:constructor running!
constructor running!
operator = running!
总结:
Test test1(0,0); //调用构造函数
Test test2 = test1; //调用复制构造函数
Test test3(test1); //调用复制构造函数
Test test4; //调用构造函数
test4 = test1; //调用拷贝赋值操作符
如果一个类的成员也是一个类类型,那么,成员的初始化会调用什么函数呢?
1.如果采用成员初始化列表的形式,则调用复制构造函数
2.如果在构造函数体内对成员初始化,则先调用构造函数,然后调用赋值操作符。
同样,我们也来看一个例子:
//头文件
#ifndef CONSTRUCTOR_H_
#define CONSTRUCTOR_H_
#include <iostream>
using namespace std;
class Test
{
public:
Test(int i=0,int j=0):x(i),y(j){cout<<"constructor running!"<<endl;}
Test(Test & t){x=t.x;y=t.y;cout<<"copy constructor running!"<<endl;}
operator=(Test &t){x=t.x;y=t.y;cout<<"operator = running!"<<endl;}
private:
int x;
int y;
};
class ComTest
{
public:
ComTest();
ComTest(Test &f):t(f){} //方法一
// ComTest(Test &f){t = f;}//方法二,把注释“//”放到上一行
private:
Test t;
};
#endif //CONSTRUCTOR_H_
在main函数中,我们执行以下语句:
Test test1(0,0);
ComTest c1(test1);
输出:constructor running!
copy constructor running!
当我们采用方法二,即把注释掉第二个构造函数时,
输出:constructor running!
constructor running!
operator = running!
总结:当类中有类类型的成员时,最好采用成员初始化列表的形式来初始化,这样效率会更高些!