《Effective Modern C++》学习笔记 - Item 11: 倾向于使用delete而不是private+只声明不定义来屏蔽函数

  • 本条款的原英文标题是 “Prefer deleted functions to private undefined ones”,不太好理解,笔者根据内容做了个转述。想表达的是:当你需要屏蔽掉某个特定的函数时,使用C++11的 delete 特性而不是像C++98中将函数声明为 private 且不给定义
  • 如果你在给其他开发者提供函数或库,有时你会希望阻止他们调用某些函数,但这些函数又被C++自动生成了。该问题主要集中于复制构造函数和赋值运算符上(先不考虑C++11新引入的移动构造函数)。例如,iostream 中的输入和输出流都继承于 basic_ios 类。我们不希望这些流被复制,所以要禁用掉它的复制构造函数和赋值运算符。C++98中声明如下:
template <class charT, class traits = char_traits<charT> >
class basic_ios : public ios_base {
public:
	...
private:
	basic_ios(const basic_ios& ); // not defined
	basic_ios& operator=(const basic_ios&); // not defined
};
  • C++98时代,做到该效果的方法正如以上所示:声明它们,以覆盖掉编译器自动生成的版本;访问权限设为 private,防止无关类调用它们;只声明不定义,防止 friend 类或自己内部调用它们。结果来说,当无关类试图调用时,会报编译错误;友元类或自身内部试图调用时,会报链接错误
  • C++11中要实现该效果可以用一个更好的方法:delete 关键字。例如当前MSVC的 basic_ios 是这样实现的:
    在这里插入图片描述
  • 此时不需再用 private 限制访问权限的方式禁止外部调用。相反地,它们一般应该被定义为 public。因为函数的访问权限会在是否被 delete 状态之前检查,如果声明为 private,外部调用会报访问权限的错误,而友元类调用会报 delete 的错误(类似C++98的情况)。而我们希望的是所有情况都统一报 delete 错误。
  • delete 的另一个重要优势在于:任何函数都可以被声明为 delete,而 private 只能作用于类的成员函数上。例如有一个非成员函数 bool isLucky(int number) 判断输入整数是否是“幸运数”。可惜由于隐式转换的存在,传入一个 a,或 true,或 3.5 的调用都是合法的。在C++11中,我们可以用 delete 重载函数的方式明确拒绝这些参数:
bool isLucky(int number) { ... }

// 以下调用均能通过编译
if (isLucky(1)) 	...
if (isLucky('a')) 	...
if (isLucky(true)) 	...
if (isLucky(3.5))	...

// delete掉不想接收类型参数的重载函数后,以上调用报错
bool isLucky(char) = delete;
bool isLucky(bool) = delete;
bool isLucky(double) = delete;
  • 也许你已经联想到了接下来的发展:delete 还能用于阻止模板对于某种特定参数类型的实例化!例如你要写一个处理裸指针的模板函数,我们知道 void*char* 类型的指针比较特殊(前者不能解引用,后者一般指字符串而非单字符),一般需要单独处理。假设这里就是要拒绝这两种参数,你可以通过写出模板的特化形式,并将它们 delete 掉来实现:
template<typename T>
void processPointer(T* ptr) { ... }

template<>
void processPointer<void>(void*) = delete;
template<>
void processPointer<char>(char*) = delete;

int* pi, char* pc, void* pv;
processPointer(pi);	// ok
processPointer(pc);	// error
processPointer(pv);	// error
  • C++98无法处理非成员函数。然而有趣的是就算是类内的成员模板函数,它也无法处理,因为无法将模板的访问权限为 public 而将其特化版本设为 privatedelete 方法不会有这个问题,因为二者都是被声明为 public 的。

总结

  1. delete,不要用 private undefined。
  2. 包括非成员函数和模板实例化函数都能被 delete 掉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值