Explicitly disallow the use of compiler-generated functions you do not want.
笔者注:本书早在C++11之前就被写出,所以作者在这里的所有方法,全部为C++11之前的做法。
在C++11之后,我们可以使用更加简洁的语法,更加可读的代码来完成同样的 *** 作。
如题目,为了避免一些不必要的麻烦 若不想用编译器自动生成的构早函数,就应该明确的拒绝,这样的做法很有意义。
世界上没有任何一片雪花是一样的,那我们就不能复制一个雪花对象,换句话说,我们不希望学花类又拷贝构造函数和拷贝赋值运算符。
我们可以将方法声明为private,并且不予任何的实现,这样对于类的外部来说,是完全不可用的。
我们就能达到类似删除这个方法的 *** 作(编译器通常会提供一些默认的方法),比如这样。
class Snowflake
{
private:
string shape;
Snowflake(const Snowflake &);
Snowflake& operator=(const Snowflake&);
public:
Snowflake(const string & _shape) : shape(_shape) { }
};
当我们这样调用的时候
int main()
{
Snowflake sf1("big");
Snowflake sf2 = sf1;
return 0;
}
会给出XXX函数不可方访问的编译器错误。
将链接期或者运行期的错误移动至编译器的当然是好事,毕竟越早的侦测出错误越好。
这样写出来的类还不能对付友元函数或者是其他成员调用——我们是想彻底的 ”删除“ 这个方法,不希望它被任何形式的调用。
这样还是会导致一些链接期间的错误。
我们有一个更好的实现方法。
就是专门封装一个基被类用于继承——控制子类中的方法可调用情况。
也就是这样。
class Uncopyuable
{
private:
Uncopyuable(const Uncopyuable &);
Uncopyuable & operator=(const Uncopyuable &);
protected:
Uncopyuable() {}
~Uncopyuable() {}
};
class Snowflake : private Uncopyuable
{
private:
string shape;
public:
Snowflake(const string & _shape) : shape(_shape) { }
};
因为在编译器在为子类生成方式时会调用器对应父类的方法——父类中的方法被声明为了private,这样无论是友元还是成员函数调用,都会获得一个编译期间的错误——非常的人性。
关于书中其他的一些细节,还是不提了,C++11已经给了我们一个足够好的解决办法——那么我们问什么不使用呢?
C++11的方法很简单,如果我们想删除某一个方法,我们可以明确的指定其是被删除的(当然是不能定义的了,上一种方法你可以定义,单使用C++11语法就真的delete了)。
class Snowflake
{
Snowflake(const Snowflake &) = delete;
Snowflake& operator=(const Snowflake&) = delete;
private:
string shape;
public:
Snowflake(const string & _shape) : shape(_shape) { }
};
还是十分的方便。
请记住
为驳回编译器自动(暗自)提供的功能,儿科将相应的成员函数声明为private并且不予实现。
使用像Uncopyabel这样的base class也是一种做法。
笔者加:
C++中使用delete关键字课很好的解决这类问题
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)