删除函数和private未定义函数

删除函数的应用场景


通常让函数是删除函数的定义是这样的:

class CPerson
{
public:
	CPerson(const CPerson&) = delete;
}

void IsLucky(int nNumber);

void IsLucky(char) = delete;
void IsLucky(double) = delete;// 拒绝double和float型别
void IsLucky(bool) = delete;

而这样的函数通常是编译器为我们合成的函数,例如复制拷贝构造、复制赋值函数,也通常是禁止参数隐式转换的函数,就像上面的函数IsLucky强制限定参数类型为int, 顺便提一下,double 的重载的注释写到:拒绝double和float型别,如果给 float一个转换为int或者double的可能性,C++总是倾向于转化为double的, 以float类型调用IsLucky总是调用对应的double重载,而不是int类型的那个重载

删除函数也能应用于模板具体实现,例如有如下模板:

template<class T>
void ProcessPointer(T* ptr);

如果我们想避免使用void*char*const void*const char*调用ProcessPointer,可以这样实现:

template<>
void ProcessPointer(void*) = delete;

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

template<>
void ProcessPointer(const void*) = delete;

template<>
void ProcessPointer(const char*) = delete;

void*指针无法对其执行提领、自增、自减等操作,而char*基本表示C风格的字符串,而不是指向单个字符的指针

如果类内部的函数模板,按照C++98的实现手法是没办法做到在类作用域内声明具体模板的,模板特化是必须在名字空间作用域而非类作用域内撰写,成员函数模板可以在类外(即名字空间作用域)作为删除函数

实现手法


C++98实现删除函数的效果是通过这些函数声明为private来阻止客户调用他们。故意不定义它们是因为,如果有函数访问这些 函数(通过成员函数或者友好类)在链接的时候会导致没有定义而触发的错误(无法解析的外部符号)

C++11中的实现就像上面的例子所示函数后面= delete

通常删除函数会被声明为public,而非private,当客户代码尝试使用某个成员函数是,C++会先检查可访问性,后检查删除状态,当客户代码试图调用某个private删除函数时,编译器只是抛出该函数为private的错误,把函数声明为public会得到更好的错误信息

任何函数都能成为删除函数,像上面的例子中函数IsLucky并不是类成员函数,C++98的实现手法只能应用于类中

最后


优先使用删除函数,而不是private未定义函数

任何函数都可以删除,包括非成员函数和模板具体实现