类的构造函数、析构函数与赋值函数

类的构造函数、析构函数与赋值函数

1、一个空类,编译器会默认为其生产六个函数,常用的有四种

class A

{

A(void);  // 缺省的无参数构造函数  

A(const A &a); // 缺省的拷贝构造函数  

~A(void);  // 缺省的析构函数  

A & operate =(const A &a); // 缺省的赋值函数

}


很多人认为编写一个空类,编译器就会做这些事,错了,这些缺省函数只在需要的时候编译器才会生成,也就是如果不需要,那么就不会生成。

2、构造函数

(1)构造函数尽量用初始化列表进行初始化,效率高

class A

{

public:

A();

A(string s, int i):name(s), id(i){} ; // 初始化列表

private:

string name;

int id;

};

(2)const只能在初始化列表中进行初始化,此外每个类对象的const变量的值并不一样,若要定义一个类常量,用enum。

(3)若类存在继承关系,派生类必须在初始化列表中调用基类的构造函数,跟java一样,只是java已经默认在首行调用个。1. class B : public A   

{

B(string s, int i);// B的构造函数  

};   

B::B(string s, int i) : A(s, i) // 在初始化表里调用A的构造函数  

{   


3、析构函数

将2中得初始化列表修改为

A(string s, int i):id(i), name(s){} ; // 初始化列表

初始化顺序该是如何呢?不管怎么样,成员初始化都是遵循声明顺序的,为什么呢?

因为构造函数可以有多个,而析构函数就一个,如果没有一个统一的顺序,那么析构函数就无法得到一个统一的逆序。

4、可否在构造函数中和析构函数中调用虚函数呢?

含有纯虚函数的基类不能构造出对象,所以在基类中得构造函数和析构函数中不能调用纯虚函数。

对于非纯虚函数,可以调用,但是派生类Derived构造对象时需先调用基类的构造函数,此时基类构造函数中调用的虚函数仍属于基类,因为派生类对象还未构造完成;反之析构函数也是,析构完派送类对象时,最后析构基类部分时的非纯虚函数仍调用的基类。

举例:

class ClassA

{

public:

ClassA()

{

cout<<"ClassA::ClassA() begin"<<endl;

Print();

cout<<"ClassA::ClassA() end"<<endl;;

}

virtual void Print()

{

cout<<"ClassA::Print()"<<endl;

}

virtual ~ClassA()

{

cout<<"ClassA::~ClassA() begin"<<endl;

Print();

cout<<"ClassA::~ClassA() end"<<endl;;

}

};


class ClassB : public ClassA

{

public:

ClassB()

{

cout<<"ClassB::ClassB() begin"<<endl;

Print();

cout<<"ClassB::ClassB() end"<<endl;;

}


void Print()

{

cout<<"ClassB::Print()"<<endl;

}


~ClassB()

{

cout<<"ClassB::~ClassB() begin"<<endl;

Print();

cout<<"ClassB::~ClassB() end"<<endl;;

}

};


int main(void)

{

ClassB* pB = new ClassB;

cout<<endl;

ClassA* pA = pB;

pA->Print();

cout<<endl;


delete pB;

return 0;

}

ClassA::ClassA() begin
ClassA::Print() //派生类还未构造完成,调用的虚函数属于基类
ClassA::ClassA() end
ClassB::ClassB() begin
ClassB::Print()
ClassB::ClassB() end


ClassB::Print() //派生类构造完成,调用的虚函数属于派生类


ClassB::~ClassB() begin
ClassB::Print()
ClassB::~ClassB() end
ClassA::~ClassA() begin
ClassA::Print() //派生类部分析构完成,调用的虚函数属于基类
ClassA::~ClassA() end



5、赋值函数

这部分我把缺省的拷贝构造函数和缺省的赋值函数放在一块比较

A(const A &a); // 缺省的拷贝构造函数  

A & operate =(const A &a); // 缺省的赋值函数

二者最大的区别:缺省的拷贝构造函数属于构造函数,对象还未创建,没有返回值;缺省的赋值函数属于普通函数,对象已经创建,有返回值。

此外拷贝构造函数不需要检验源对象是否和新建对象相同,而赋值函数需要检验源对象是否和被赋值对象相同,因为如果被赋值的对象分配了内存,需要先释放原来的内存资源然后根据源对象重新分配内存,如果两者相同,等于把自身的内存释放了,就会出现错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值