1、=delete
函数声明时,末尾添加=delete表示此函数被禁用,通常用于禁用复制构造函数、赋值运算符等特定函数。使用方法如下
class MyClass {
public:
// 拷贝构造函数被删除
MyClass(const MyClass&) = delete;
// 拷贝赋值运算符被删除
MyClass& operator=(const MyClass&) = delete;
}
2、=default
用于知识编译器生成默认的构造函数、拷贝构造函数、赋值运算符等特定函数
例如如下代码,表示默认构造函数和拷贝构造函数都被使用,且使用编译器默认的定义(这样我们就不需要写定义了)
class MyClass {
public:
MyClass() = default; // 默认构造函数
MyClass(const MyClass&) = default; // 默认拷贝构造函数
};
3、override
表示此函数是重写了基类中的虚函数,有助于编译器检查是否完成重写。如果编译器在编译时检查到此函数在基类中没有找到匹配的虚函数,则编译器会报错。
class Base {
public:
virtual void foo(int x) {
std::cout << "Base foo: " << x << std::endl;
}
};
class Derived : public Base {
public:
void foo(double y) override { // 错误:没有正确重写
std::cout << "Derived foo: " << y << std::endl;
}
};
int main() {
Base* b = new Derived();
b->foo(5); // 调用的是 Base::foo
delete b;
return 0;
}
4、final
用于指示一个虚函数不能被重写,或者一个类不能被继承
class Base {
public:
virtual void func() final; // func不能被重写
};
class Derived final : public Base {
// Derived 不能被继承
};
5、noexcept
用noexcept声明函数表示此函数不会抛出异常。编译器在处理这样的函数时,就不会进行不必要的异常安全处理,从而提高性能。并且,noexcept可以确保函数在发生错误(异常)时,会直接终止程序,不会进入异常处理模块,确保程序不会进入未被定义的状态。
例如如下代码:
虽然func内部抛出异常后,程序会直接调用
std::terminate()结束运行,而不会进入catch程序块。
void func() noexcept {
throw std::runtime_error("This will terminate the program");
}
int main() {
try {
func();
} catch (...) {
// 不会被执行
}
return 0;
}
6、explicit
用于构造函数和转换运算符,防止隐式类型转换。
隐式类型转换也就是自动类型转换,是指编译器在不需要显式制定转换的情况下自动将一种数据类型转换为另外一种数据类型的过程。这个过程通常发生下表达式求值以及函数调用的过程中。
例如如下
int a = 10;
double b = a; //这里将变量a的int型数据隐式转换为double型数据赋值给了b
void func(double x){}
int main()
{
int a = 10;
func(a); //在调用函数时,发生了int型数据转换为double型数据的隐式类型转换
}
使用explicit声明的构造函数和转换操作符,将禁止隐式类型转换
class MyClass {
public:
explicit MyClass(int x):__x(x) {
}
explicit operator int() const {
return __x;
}
private:
int __x = 0;
};
void func(MyClass obj) {
}
int main() {
// func(10); // 发生错误!隐式转换,调用 MyClass(int) 被禁止
MyClass obj(10); // 正确!显式转换,调用MyClass(int)构造函数
//int x = obj; // 发生错误!MyClass类型转换int隐式转换被禁止,调用operator int()
int y = static_cast<int>(obj); //正确!MyClass类型转换int显式转换,调用operator int()
return 0;
}
需要注意的是,explicit
仅适用于单参数的构造函数和转换运算符。
7、const
const修饰成员函数:
1)该成员函数不能修改类成员变量;
2)该成员函数不能调用其他没有被const修饰的成员函数(无论这个成员函数是什么行为);
class MyClass
{
public:
void RData() const{
//db = 9; //ERROR: 编译不过,不能改变成员变量
//Setdb(8); //ERROR: 编译不过,不能调用没有被const修饰的成员函数
//Getda(); //ERROR: 编译不过,不能调用没有被const修饰的成员函数
cout << da << " " << db << endl; //OK
}
void Setdb(int b){
db = b;
}
int Getda(){
return da;
}
const int da = 0;
int db = 1;
};