条款05:了解C++默默编写并调用那些函数
相信大多数学习完C++的学生对于这个问题是知道答案的,但对于还未学习完C++的同学可能就不是很清楚了。是这样的,对于C++而言若是你在一个类中未定义构造函数,拷贝构造函数,析构函数,赋值运算符重载的时候,编译系统会默认给提供的,也就是这四个函数你定义了那个就使用的是你定义的,若你未定义则使用的是默认的。
class A{};
class A
{
A(){ cout<<"is A"<<endl };
};
用这个举例子,两个类都有上面所提到的四个函数,但是第一个A的四个函数都是默认的,而第二个A除了构造以外的三个函数都是默认的。也就是只要你定义了一个类那么它就具备这四个函数。
class A
{
public:
A(std::string str,int val)
:_str(str),
_val(val)
{}
std::string getstr()
{
return _str;
}
private:
std::string _str;
int _val;
};
int main()
{
A a("hello",1);
A b("word",2);
A c("emm",3);
A d(a);
c = a = b;
std::cout<<c.getstr()<<std::endl;
std::cout<<d.getstr()<<std::endl;
return 0;
}
输出:
word
hello
C++这样的设定方便是方便,但却有着很大的弊端,比如的std::string str
定义为std::string& str
想一想会发生什么。所以再构建类的时候最好把这四个方法都写一遍。
条款06:若不想使用编译器自动生成的函数,就该明确拒绝
也就我上面提到,不想使用默认自己写一遍避免因自动生产而造成程序错误。
再者就是不用这几种方法中的其中一种且要避免编译器自动生成就把它放到私有里不予实现。对于构造和析构而言这步似乎不需要,但对于带有Copy性质的函数就有必要了,因为在你不想用且不去声明这类方法的时候,编译器又会为你自动生产。
class A
{
public:
*****
private:
A(const A&);
A& operator=(const A&);
};
这样处理之后似乎就可以,但是这样其实还是有漏洞的,因为通过member
函数和friend
函数还是可以调用的,所以这样并非是绝对安全的。所以还需要这样处理。
class UncopyBase
{
protected: //允许派生类对象的构造和析构
UncopyBase(){}
~UncopyBase(){}
private: //阻止copy
UncopyBase(const UncopyBase&);
UncopyBase& operator=(const UncopyBase&);
};
class A : private UncopyBase
{
***********
};
这样就完美了。