11优先使用delete关键字删除函数而不是private却又不实现的函数:
我们想要阻止其他程序员使用某个函数时,只需要不声明该函数即可,但是C++有时候会替你声明函数,比如自动生成的成员函数,本文中目前只考虑拷贝构造函数和赋值运算符函数。C++11以前我们的做法是将这些函数声明为private,并且不去定义它们。
举例来讲,在C++标准库中输入输出流库继承于basic_ios,对输入流和输出流进行复制是不可取的,C++98中的basic_ios的声明如下:
template <class charT, class traits = char_traits<charT> >
class basic_ios : public ios_base {
public:
// ...
private:
basic_ios(const basic_ios&); // 不可复制
basic_ios& operator=(const basic_ios&); // 不可赋值
};
在C++11中,有了删除函数,使用delete可以使它们标识为删除函数,我们可以将上述代码改为:
template <class charT, class traits = char_traits<charT> >
class basic_ios : public ios_base {
public:
// ...
basic_ios(const basic_ios&) = delete;
basic_ios& operator=(const basic_ios&) = delete;
// ...
};
使用delete关键字和将函数声明为private看起来只是不同风格的选择,但实际上是有区别的。
- 使用delete删除的函数无法通过任何方法调用,即使是成员函数或友元函数中的代码也是无法调用的。相对于private的做法来讲,这是一种改进。
- 删除函数往往被声明为public。这样做的好处是,当客户代码尝试调用某个成员函数时,C++会先校验其可访问性,后校验删除状态。这么一来,当客户代码尝试调用某个private函数,编译器只会提示该函数为private。所以把新的delete函数声明为public会得到更好的错误信息。
- 任何函数都可以成为删除函数,但是只有成员函数才能被声明为private。
举例来讲,如果我们有一个函数 bool isLucky(int number); C++中很多类型可以隐式转换到int中,所以会出现以下无意义的代码调用
if (isLucky('a')) ...
if (isLucky(true)) ...
if (isLucky(3.14)) ...
当我们想要阻止这样的调用的时候,我们可以通过delete关键字来删除对应的重载版本
bool isLucky(int);
bool isLucky(char) = delete;
bool isLucky(bool) = delete;
bool isLucky(double) = delete;
isLucky(0);
isLucky(true); //调用失败
isLucky(false); //调用失败
isLucky('a'); //调用失败
isLucky(3.15); //调用失败
这样再出现上述调用的时候,编译器会提示上述函数已经删除,无法调用。
请记住:
- 优先选用删除函数,而非private未定义的函数
- 任何函数都可以被删除,包括非成员函数和模板函数
Comments NOTHING