子类可以重写父类的方法,从而实现扩展自己的行为,但是某些情况下。
我们可能并不希望子类能够重新实现父类的方法,我们希望完全的终止重写行为,这个时候我们需要借助关键字:final.
C++11和JAVA一样,使用关键字:final,来阻止子类对父类定义的方法进行重写.
g++ 210.cpp -o test -std=c++11
#include <iostream>
using namespace std;
class Base {
public:
void msg1() {
cout << "Base::msg1()" << endl;
}
virtual void msg2() {
cout << "Base::msg2()" << endl;
}
virtual void msg3() {
cout << "Base::msg3()" << endl;
}
};
class Derived : public Base {
public:
void msg1() {//不允许使用final ,msg1不是virtual函数
cout << "Derived::msg1() " << endl;
}
void msg2() final {
cout << "Derived::msg2() " << endl;
}
void msg3() {
cout << "Derived::msg3() " << endl;
}
};
class MyMsg :public Derived {
public:
void msg1() {//不允许使用final ,msg1不是virtual函数
cout << "MyMsg::msg1() " << endl;
}
// void msg2() {
// } //不合法,无法重写final函数
void msg3() {
cout << "MyMsg::msg3() " << endl;
}
};
int main()
{
Base* base = new Derived;
base->msg1(); //无virtual 关键字
base->msg2();//有virtual 关键字 --会实现动态编连
//继承类重写的函数,自动具有virtual属性,会实现动态编连
Derived* msg = new MyMsg;
msg->msg3(); //调用MyMsg的msg3
return 0;
}
执行结果输出如下:
Base::msg1()
Derived::msg2()
MyMsg::msg3()
注意 :final关键字只能用在virtual方法中,只能用于在中途终止派生类的重写行为.
补充知识点:
在C++中重载有一个特点,就是对于基类中声明为virtual的函数,之后的重写版本都不需要再声明为virtual了,即使在派生类中声明了关键字virtual,也会自动被编译器所忽略的.
OK,到了这里,我们会发现一个问题。
我们看继承类Derived,这个类我们是继承于Base,并且重写了Base的方法msg1() msg2().
但是注意这里,我们会引发出一个问题:
如果我们不看Base,或者继承的层次多了,我们就会犯一个迷糊:
这个时候,我们已经无法判断出msg1,msg2到底是Derived的私有方法,还是重写的父类的方法.
所以我们引入了override关键字来帮助我们进行区分.
class Derived : public Base {
public:
void msg1() {//不允许使用final ,msg1不是virtual函数
cout << "Derived::msg1() " << endl;
}
void msg2() final {
cout << "Derived::msg2() " << endl;
}
void msg3() {
cout << "Derived::msg3() " << endl;
}
};
所以改进后的写法是:
class Derived : public Base {
public:
void msg1() {//不允许使用final ,msg1不是virtual函数
cout << "Derived::msg1() " << endl;
}
void msg2() final {
cout << "Derived::msg2() " << endl;
}
void msg3() override {
cout << "Derived::msg3() " << endl;
}
};
这样我们就很容易的知道:
msg3()这个方法其实是重写的基类的方法.
注意:
override和final一样,只能用于virtual函数,非virtual函数使用final和override关键字一律不合法.
使用override声明的函数不能重写基类成员.
为什么呢?因为override设计的本意是告诉你此函数是纯虚函数,可是基类成员函数如果不纯虚函数而又添加了override,那么就失去了意义了.