先有如下代码:
class A
{
public:
A()
{
this->m_byte = (char*)malloc( 1 );
}
~A()
{
free( this->m_byte );
}
void show_hello() const
{
cout << “hello! A object is work!” << endl;
}
private:
char* m_byte;
};
经过测试,这是一段没有问题的代码。同时收到同事的反馈:效果不错!我的工作简单多了!
class B :public A
{
public:
B(const A &a) // B的构造函数
{
}
};
int main()
{
A* first = new A;
B* second = new B(*first);
second->show_hello();
delete first;
delete second;
// system( “pause” );
return 0;
}
另一位同事B提出了不同的意见: second->show_hello() 报告: I am A object! 这是多么荒谬的事情!B同事拿来 砖头厚的 < head first design pattern >,引用其中的原话:多用组合,少用继承。(Favor composition over inheritance)。于是他写出了如下代码:
class B
{
public:
B(const A &a) // B的构造函数
{
this->m_a = a;
}
private:
A m_a; // 成员对象
};
问题出现了!
原因:没有声明拷备构造的情况下, A 对象的 m_byte的地址并拷备了两份,并被两次释放。
怎样解决:
在Class A 中增加拷备构造函数:
A& operator =( const A &other)
{
return *this;
}
这个函数看起来什么都没有做。是的,它确实什么都没做。让这并不意味着它没有贡献。它的贡献在于:它让编译器不做什么--声明这个函数后,编译器不再为此类添加默认的 operator = 函数。默认地,c++为为每个类添加四个函数:构造、析构、拷备构造、赋值。
参考资料:
高质量C++/C编程指南(林锐)之九-类的构造函数、析构函数与赋值函数
文章目录:
第一篇:c++导航
1 c++加了什么之一? this 指针
2 c++ 加了什么之二--虚表( virtual table)
3 更加广泛的 const 关键字
第二篇:编译期错误
1、模板参数转为 void?
1、引用( referance )是个啥玩意儿
2、模板编译的噩梦
第三篇:让人崩溃的运行时错误( c++ run time error )
1、模板参数转为 void*的错误(参考赵工的错误)
2、vector 还是 list。
3:啥都不做带来的灾难--赋值与拷备构造?
4:默认的不总是对的--让人崩溃的虚析构函数。
5:临时对象在哪里
如果一个临时性对象被绑定于一个reference,对象将残留,直到被初始化之reference的生命结束,或直到临时对象的生命范畴(scope)结束——视哪一种情况先到达而定。(《深度探索C++对象模型》P275)
这里的“reference的生命结束”和“临时对象的生命范畴(scope)结束”有什么区别?感觉说的是一样的。谁能针对这两种情况,举两个例子?
(To ckt1120 :我是感觉他说的后半句不对。查了C++标准,对引用这种情况,并没有他说的那种情况)