携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情
💦 C++11 final和override
✔ 测试用例一:
class A final
{};
class B : public A
{};
int main()
{
return 0;
}
#include<iostream>
using namespace std;
class Car
{
public:
virtual void Drive() final
{}
};
class Benz : public Car
{
public:
virtual void Drive()
{
cout << "Benz-舒适" << endl;
}
};
int main()
{
return 0;
}
-
final 修饰类,表示该类不能再被继承。同样是实现出一个不能被继承的类,C++11 中的 final 相对 C++98 中对构造函数私有化更为彻底。
-
final 修饰虚函数,表示该虚函数不能再被重写,重写则会报错。
✔ 测试用例二:
#include<iostream>
using namespace std;
class Car
{
public:
virtual void Drive() {}
};
class Benz : public Car
{
public:
//virtual void Drive() override//ok,重写
//{
// cout << "Benz-舒适" << endl;
//}
//void Drive() override//ok,属于重写的例外
//{
// cout << "Benz-舒适" << endl;
//}
virtual void Drive(int) override//err,没有完成重写
{
cout << "Benz-舒适" << endl;
}
};
int main()
{
return 0;
}
-
override 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写则编译报错。
💦 重载、重定义(隐藏)、重写(覆盖)的对比
💦 抽象类概念
✔ 测试用例三:
#include<iostream>
using namespace std;
class Car//抽象类
{
public:
virtual void Drive() = 0;//纯虚函数
};
class Benz : public Car
{
public:
virtual void Drive()//重写纯虚函数
{
cout << "Benz-舒适" << endl;
}
};
class BMW : public Car
{
public:
virtual void Drive()//重写纯虚函数
{
cout << "BMW-操控" << endl;
}
};
int main()
{
Benz bz;
Car* pBenz = new Benz;
pBenz->Drive();
Car* pBMW = new BMW;
pBMW->Drive();
return 0;
}
-
在虚函数的后面写上 = 0,则这个函数为纯虚函数,包含纯虚函数的类叫做抽象类 (也叫接口类,你可以模糊的认为一个类的公有成员函数是接口,但更多是因为纯虚函数只有声明,没有实现,所以叫接口类。通常还是叫抽象类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象,也就是说纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。
理解接口类和抽象类 ❓
接口类相比抽象类的概念更广泛,你可以认为一个类的公有成员函数是接口,换一个角度,如果一个类设计的不规范,也不能说公有的成员函数就是接口。但更重要的是纯虚函数只有声明,没有定义,所以有些地方叫接口类。这个概念比较模糊,但是也要能理解有些地方叫接口类,但是更重要的还是要理解它叫抽象类。
抽象这个词,我们理解的场景是 “ 你长的好抽象 ” 或 “ 抽象派画家画的画好抽象 ”。本质抽象类指的是在现实世界中没有具体的对应实物,也就没必要实例化对象,比如说车去实例化对象,那么对象是卡车、公交车还是观光车?车是抽象的,它实例化的对象没有具体对应实物,所以我们可以把它实现为抽象类,让它不能实例化对象。
-
抽象类可以创建指针,但是只能指向子类,因为父类不能创建对象。
💦 接口继承和实现继承
- 这个概念了解下,有些书上会提,主要是为了避免以后遇到了不知道它讲的啥。
- 普通函数的继承是一种实现继承,派生类继承了基类,可以使用函数,继承的是函数的实现。虚函数的继承是接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达到多态,继承的是接口。所以不实现多态,不要把函数定义成虚函数。