EffectiveC++第三章构造函数析构函数和赋值操作符学习笔记
2010-02-10 12:27
211 查看
条款11: 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
这个缺省的赋值操作符会执行从a的成员到b的成员的逐个成员的赋值操作,对指针(a.data和b.data) 来说就是逐位拷贝。
用delete去删除一个已经被删除的指针,其结果是不可预测的。
解决这类指针混乱问题的方案在于,只要类里有指针时,就要写自己版本的拷贝构造函数和赋值操作符函数。
对于有些类,当实现拷贝构造函数和赋值操作符非常麻烦的时候,特别是可以确信程序中不会做拷贝和赋值操作的时候,去实现它们就会相对来说有点得不偿失。前面提到的那个遗漏了拷贝构造函数和赋值操作符的例子固然是一个糟糕的设计,那当现实中去实现它们又不切实际的情况下,该怎么办呢?很简单,照本条款的建议去做:可以只声明这些函数(声明为private成员)而不去定义(实现)它们。
// 去掉默认的赋值函数和默认的拷贝构造函数
// vc 2005 express
代码#include <iostream>
using std::cout;
using std::endl;
using std::cin;
class Property
{
public:
Property(unsigned int age, unsigned int weight)
: _age(age), _weight(weight)
{
}
unsigned int _age;
unsigned int _weight;
};
class base
{
public:
base(int initialvalue = 0)
: x(initialvalue)
{
prop = new Property(22, 99);
}
void GetWeight()
{
cout << prop->_weight << endl;
}
void Relase()
{
delete prop;
prop = 0;
}
base & operator=(const base & b)
{
prop = new Property(b.prop->_age, b.prop->_weight);
return *this;
}
private:
int x;
Property * prop;
};
class derived: public base {
public:
derived(int initialvalue)
: base(initialvalue), y(initialvalue) {}
derived& operator=(const derived& rhs);
private:
int y;
};
derived& derived::operator=(const derived& rhs)
{
if (this == &rhs) return *this;
base::operator=(rhs); // 调用 this->base::operator=
y = rhs.y;
return *this;
}
void assignmenttester()
{
derived d1(0);
derived d2(1);
d1 = d2;
d2.GetWeight();
d1.GetWeight();
d2.Relase();
d1.GetWeight();
cin.get();
}
void main()
{
assignmenttester();
}
条款17: 在operator=中检查给自己赋值的情况
采用地址相等的定义,一个普通的赋值运算符看起来象这样:
c& c::operator=(const c& rhs)
{
// 检查对自己赋值的情况
if (this == &rhs) return *this;
...
}
这个缺省的赋值操作符会执行从a的成员到b的成员的逐个成员的赋值操作,对指针(a.data和b.data) 来说就是逐位拷贝。
用delete去删除一个已经被删除的指针,其结果是不可预测的。
解决这类指针混乱问题的方案在于,只要类里有指针时,就要写自己版本的拷贝构造函数和赋值操作符函数。
对于有些类,当实现拷贝构造函数和赋值操作符非常麻烦的时候,特别是可以确信程序中不会做拷贝和赋值操作的时候,去实现它们就会相对来说有点得不偿失。前面提到的那个遗漏了拷贝构造函数和赋值操作符的例子固然是一个糟糕的设计,那当现实中去实现它们又不切实际的情况下,该怎么办呢?很简单,照本条款的建议去做:可以只声明这些函数(声明为private成员)而不去定义(实现)它们。
// 去掉默认的赋值函数和默认的拷贝构造函数
// vc 2005 express
代码#include <iostream>
using std::cout;
using std::endl;
using std::cin;
class Property
{
public:
Property(unsigned int age, unsigned int weight)
: _age(age), _weight(weight)
{
}
unsigned int _age;
unsigned int _weight;
};
class base
{
public:
base(int initialvalue = 0)
: x(initialvalue)
{
prop = new Property(22, 99);
}
void GetWeight()
{
cout << prop->_weight << endl;
}
void Relase()
{
delete prop;
prop = 0;
}
base & operator=(const base & b)
{
prop = new Property(b.prop->_age, b.prop->_weight);
return *this;
}
private:
int x;
Property * prop;
};
class derived: public base {
public:
derived(int initialvalue)
: base(initialvalue), y(initialvalue) {}
derived& operator=(const derived& rhs);
private:
int y;
};
derived& derived::operator=(const derived& rhs)
{
if (this == &rhs) return *this;
base::operator=(rhs); // 调用 this->base::operator=
y = rhs.y;
return *this;
}
void assignmenttester()
{
derived d1(0);
derived d2(1);
d1 = d2;
d2.GetWeight();
d1.GetWeight();
d2.Relase();
d1.GetWeight();
cin.get();
}
void main()
{
assignmenttester();
}
条款17: 在operator=中检查给自己赋值的情况
采用地址相等的定义,一个普通的赋值运算符看起来象这样:
c& c::operator=(const c& rhs)
{
// 检查对自己赋值的情况
if (this == &rhs) return *this;
...
}
相关文章推荐
- EffectiveC++第三章构造函数析构函数和赋值操作符学习笔记
- 面向对象的程序设计学习笔记-构造函数和析构函数
- C/C++学习笔记:String类的构造函数、析构函数和赋值函数
- C++学习笔记_2:单一继承时的构造函数与析构函数
- C++学习笔记(4)——派生类的构造函数和析构函数
- c++学习笔记4,派生类的构造函数与析构函数的调用顺序(一)
- C++学习笔记51——在构造函数和析构函数中调用虚函数
- C++学习笔记(17)——虚函数与构造函数、析构函数
- 【C++面向对象学习笔记】-构造函数和析构函数
- C#学习笔记整理_深入剖析构造函数、析构函数
- c#学习笔记-构造函数和析构函数
- C++学习笔记(5)——基类、派生类的构造函数、析构函数的调用顺序
- C++学习笔记11 构造函数与析构函数
- c++学习笔记之构造函数和析构函数
- C++学习笔记1:构造函数和析构函数
- (原创)c#学习笔记09--定义类03--构造函数和析构函数
- C++学习笔记(六)-- 类和对象 构造函数和析构函数 const成员函数 this指针 对象数组 堆栈管理变量
- C++学习笔记12 构造函数与析构函数下
- C++ Primer 学习笔记(8): 构造函数、析构函数调用顺序
- 《C++ Primer Plus》10.3 类的构造函数和析构函数 学习笔记