前言
final、override、=default、=delete是C++11新增的一组非常具有标记意义的关键字和语法。
final关键字
该关键字修饰一个类,这个类不允许被继承,这在其他语言中早就实现了。在C++11中,final关键字要写在类名的后面。
示例:
class A final
{
};
class B : public A
{
};
override关键字
C++语法规定,在父类中加了virtual关键字的方法可以被子类重写,子类重写该方法时可以加或不加virtual关键字,示例:
class A
{
protected:
virtual void func1() {}
};
class B : A
{
protected:
virtual void func1() {}
};
class C : B
{
protected:
void func1() {}
};
带来的问题:
- 当阅读代码时,无论子类重写的方法是否添加了virtual关键字,我们都无法直观地确定该方法是否是重写的父类方法。
- 如果在子类中不小心写错了需要重写的方法的函数名,这个方法就会变成一个独立的方法,可能会违背重写父类某个方法的初衷,而编译器在编译时并不会检查到这个错误,因为这样本身也没错。
为了解决这两个问题,C++引入了override关键字。
类方法被override关键字修饰,表明该方法重写了基类的同名方法,加了该关键字后,编译器会在编译阶段做相应的检查,如果其基类不存在相同签名格式的类方法,编译器就会给出相应的错误提示。
情况1:
基类不存在,派生类标记了override的方法:
class A {};
class B : A
{
protected:
void func() override
{}
};
情形2:
基类存在,派生类标记了override的方法,但函数返回类型不同
class A
{
protected:
virtual int func() {}
};
class B : A
{
protected:
virtual void func() override
{}
};
所以需要改成:
class A
{
protected:
virtual int func() {}
};
class B : A
{
protected:
virtual int func() override
{}
};
=default语法
如果一个C++的类没有显式的给出构造函数、析构函数、拷贝构造函数、operator=这些类的函数实现,则在需要他们时,编译器会自动生成;或者在给出这些函数的声明,却没有给出实现,则编译器会在链接时报错。
如果使用=default标记,编译器会给出默认的实现。
示例:
这个是可以编译通过的,编译器生成了一个无参构造
class A {};
int main(void)
{
A a;
return 0;
}
而如果提供一个有参的构造函数,编译器会报错,因为不会产生默认无参构造函数了
class A {
public:
A(int i) {}
};
int main(void)
{
A a;
return 0;
}
这时候可以手动加上类A的无参构造函数:
class A {
public:
A() = default;
A(int i) {}
};
int main(void)
{
A a;
return 0;
}
=default最大的作用可能是在开发中简化了构造函数中没有实际初始化代码的写法。
=delete语法
既然有强制编译器生成构造函数、析构函数等函数的语法,那相应的,也有禁止编译器生成这些函数的语法,就是 =delete。
在C++98/03规范中,如果想让一个类不能被拷贝,则可以将其拷贝构造函数和operator=函数定义成private的:
class A
{
public:
A() = default;
~A() = default;
private:
A(const A& a) {}
A& operator=(const A& a) {}
};
现在有了=delete语法,可以直接使用该语法禁止编译器生成这两个函数。
class A
{
public:
A() = default;
~A() = default;
private:
A(const A& a) = delete;
A& operator=(const A& a) = delete;
};
一个空类会生成几个缺省函数
既然说到了编译器会生成默认的XX函数,那么刚好回顾一下:
一个空类会生成几个默认函数?
在以前的标准中,空类会生成六个函数:
class Empty
{
public:
Empty(); // 构造函数
~Empty(); // 析构函数
Empty(const Empty&); // 拷贝构造
Empty& operator=(const Empty&); // 赋值构造
Empty* operator&(); // 取地址
const Empty* operator&()const; // const取地址
};
在新标准中(忘了是C++11还是C++17),会生成8个缺省函数
class Empty
{
public:
Empty(); // 构造函数
~Empty(); // 析构函数
Empty(const Empty&); // 拷贝构造
Empty& operator=(const Empty&); // 赋值构造
Empty* operator&(); // 取地址
const Empty* operator&()const; // const取地址
Empty(Empty&&); // 移动拷贝
Empty& operator=(Empty&&); // 移动赋值
};