override和final標識符
override
和final
是C++引入的新的標識符
。注意是標識符不是關鍵字。
標識符和關鍵字的區別
關鍵字(KEYWORD)
:也稱保留字。它們爲語言所用,不可用於重定義或重載。
標識符(IDENTIFIERS)
:一個標識符是一個由數字,下劃線,小寫和大寫拉丁字母,和大多數 Unicode 字符組成的任意長度的序列。在聲明中,可以用標識符來命名對象、引用、函數、枚舉項、類型、類成員、命名空間、模板、模板特化、形參包、goto 標號,以及其他實體。
override和final標識符
: 擁有特殊含義的標識符,可用作對象或函數的名字,但在某些語境擁有特殊含義。
也就是說,override和final也是標識符,也可以作爲對象名,或函數名。只是在特殊的語境中有特殊的含義,和作爲對象名和函數名是不衝突的。但關鍵字不可以這樣。
例子:
#include <iostream>
class A {
public:
virtual void show() {
std::cout << "A::show(), override = " << override << std::endl;
}
private:
int override = 1;
};
class B : public A {
public:
virtual void show() override {
std::cout << "B::show(), override = " << override << std::endl;
}
private:
int override = 2;
};
int main() {
A* ptr1 = new A();
A* ptr2 = new B();
ptr1->show();
ptr2->show();
}
輸出
A::show(), override = 1
B::show(), override = 2
作爲函數名也是可以的,但不能同時命名override爲對象名和函數名,就不舉例說明了。
因爲是C++11才引入的,編譯時要指定C++11,否則編譯有告警提示
warning: override controls (override/final) only available with -std=c++11 or -std=gnu++11 [enabled by default]
override標識符
爲什麼要引入override標識符? C++11以前沒有時,是什麼樣?
還是剛纔的例子:
#include <iostream>
class A {
public:
virtual void show() {
std::cout << "A::show(), override = " << override << std::endl;
}
private:
int override = 1;
};
class B : public A {
public:
virtual void show(int a) { //變化行
std::cout << "B::show(), override = " << override << std::endl;
}
private:
int override = 2;
};
int main() {
A* ptr1 = new A();
A* ptr2 = new B();
ptr1->show();
ptr2->show();
}
輸出
A::show(), override = 1
A::show(), override = 1
因爲Class B的本意是重寫Class A的show方法。 由於參數不一致,導致是新增了一個虛函數。由於沒有重寫基類方法,無法多態調用到派生類的方法。
重寫函數必須有相同的類型,名稱和參數列表。需要人爲去保證,往往容易出現錯誤,導致和預期不一致。
當需要重寫基類方法時,使用override關鍵字,這樣可以將重寫的檢查工作交給編譯器會去做。
例子中增加關鍵字override:
...
virtual void show(int a) override {
...
編譯將報錯:
error: ‘virtual void B::show(int)’ marked override, but does not override
所有override標識符的作用是: 將重寫的檢查交給編譯器,減少人爲出錯的可能。
在重寫基類方法時,加上override標識符是正確的選擇。
final標識符
final 是在成員函數聲明或類頭部中使用時有特殊含義的標識符。其他語境中它未被保留,而且可用於命名對象或函數。
final可以用於
- 類聲明: 指定某個類不能被子類繼承。
- 函數聲明: 指定某個虛函數不能在子類中被覆蓋。
類聲明
class A final {
public:
virtual void show() {
std::cout << "A::show(), override = " << override << std::endl;
}
private:
int override = 1;
};
如果Class B繼承Class A,編譯將報錯
error: cannot derive from ‘final’ base ‘A’ in derived type ‘B’
函數聲明
virtual void show() final {
std::cout << "A::show(), override = " << override << std::endl;
}
Class B重寫show方法時,也會報錯。
注意:
- final不能用於非虛方法。除非這個非虛方法是重寫基類的方法。
- 派生類重寫基類的虛方法也可以指定爲final,表示這個方法不能再其被派生類重寫。
參考:
https://zh.cppreference.com/w/cpp/keyword
https://www.bogotobogo.com/cplusplus/C11/C11_override_final.php
https://zh.cppreference.com/w/cpp/language/override
https://zh.cppreference.com/w/cpp/language/fin