如果你实现了某个类给其他程序猿使用,但是不想让他使用某个特定函数,那我们可以直接不声明该函数即可。但是如果这个函数是编译器自动生成的,例如默认赋值函数,那我们又应该怎么做呢?
C++98中的做法是将该函数声明为private权限,这样就阻止了外部直接调用它,然后我们也不去实现它,这样当该类的其他成员函数误调用该函数时,会因为缺少定义而提示链接错误。例如:
class Test {
public:
void Fix(Test& t) {
Test t1;
t1 = t; //编译报错,使用未定义函数
}
private:
Test& operator=(const Test& t);//只声明,不定义
};
Test t1,t2;
t1 = t2; //编译报错,private权限问题
为了解决这种问题,C++11给我们提供了另一种解决该问题的方法,那就是delete关键字。上述同样的代码,只需要在赋值函数后面加上delete即可。
class Test {
public:
void Fix(Test& t) {
Test t1;
t1 = t; //编译报错,使用delete函数
}
Test& operator=(const Test& t) = delete;//只声明,不定义
};
Test t1,t2;
t1 = t2; //编译报错,使用delete函数
使用delete的一个很明显的好处就是,客户误调用delete函数时,可以直接给出函数被删除的失败原因,而非未定义这类不明确的原因。
另外一个好处就是不仅可以可以修饰成员函数,普通全局函数也可以使用delete,特别是函数重载场景时,delete还是非常好用的,因为即使这个函数虽然被删除了,但它还是程序的一部份,在重载决议时,仍然会纳入考量,特别时最后匹配到删除函数时,将会直接提示函数被删除。
// 无delete场景
// 函数原型
bool isLove(int);
isLove(12); // 匹配到isLove(int)
isLove(false); // false隐式转换为int,匹配到isLove(int)
isLove(3.5); // double隐式转换为int,匹配到isLove(int)
// 使用delete场景
bool isLove(int);
bool isLove(bool) = delete;
bool isLove(double) = delete;
isLove(12); // 匹配到isLove(int)
isLove(false); // 匹配到isLove(bool),因其为删除函数,编译报错
isLove(3.5); // 匹配到isLove(double),因其为删除函数,编译报错
最后,在删除某个模板函数(成员函数或全局函数)的某个类型的具现函数,这个只能借助delete关键字:
//全局函数
template<class T>
void TestFunc(T* ptr);
template<>
void TestFunc<void>(void*) = delete; //删除该模板的void类型具现
template<>
void TestFunc<char>(char*) = delete; //删除该模板的char类型具现
//成员函数,类内类外均可删除
class TestClass{
public:
template<class T>
void TestFunc2(T* ptr);
template<>
void TestFunc2<void>(void*) = delete; //类内删除该模板的void类型具现
};
template<>
void TestClass::TestFunc2<char>(char*) = delete; //类外删除该模板的char类型具现