C++11 在繼承的地方多了 override
和 final
兩個 keyword 可以用
在解釋之前先回顧 C++ 的繼承
C++ 繼承
- class 定義
public
: 大家都可看protected
: 只有子孫能看private
: 只有自己能看
- class 繼承
public
: 大家都知道父母和小孩的關係protected
: 只有子孫知道自己與祖先的關係private
: 只有自己知道跟父母的關係
基本上的 priority 就是 private
> protected
> public
所以在繼承的時候 priority 大的會掩蓋 priorty 小的
class A
{
public:
int x;
protected:
int y;
private:
int z;
};
class B : public A
{
// x is public
// y is protected
// z is not accessible from B
};
class C : protected A
{
// x is protected
// y is protected
// z is not accessible from C
};
class D : private A
{
// x is private
// y is private
// z is not accessible from D
};
Virutal Function
C++ 裡提供了一個 keyword 叫 virtual
,
使用 virtual 關鍵字的 method 會是 Late binding (dynamic binding),
在 runtime 的時候才會決定要 call 的 function 位址
例如 :
#include <iostream>
class A
{
public:
void func1()
{
std::cout << "func1 in A" << std::endl;
}
virtual void func2()
{
std::cout << "func2 in A" << std::endl;
}
};
class B : public A
{
public:
void func1()
{
std::cout << "func1 in B" << std::endl;
}
void func2()
{
std::cout << "func2 in B" << std::endl;
}
};
int main(int argc, char *argv[]) {
A a = A();
B b = B();
a.func1(); // func1 in A
a.func2(); // func2 in A
b.func1(); // func1 in B
b.func2(); // func2 in B
A &c = b;
c.func1(); // func1 in A
c.func2(); // func2 in B
A *ptr = nullptr;
ptr = &a;
ptr->func1(); // func1 in A
ptr->func2(); // func2 in A
ptr = &b;
ptr->func1(); // func1 in A
ptr->func2(); // func2 in B
return 0;
}
這邊可以看到,把 class B 的變數用 class A 去解讀的時候,func1 是呼叫到 class A 所定義的,
而 func2 是呼叫到 class B 所定義的,會有這樣的差別是因為 func1 沒有用 virtual
,
但是 func2 有用 virtual
,
base class 有寫 virtual 的 function 在被 call 到時會去 virtual table
裡面找真正要 call 的 function 的位址,
也才能有 late binding 的效果,沒有寫 virtual 的 function 依然會是 early binding (static binding)。
在 static binding 的情況下,ptr 要 call 的 function 的位址在 compile time 就決定了,
所以 func1 一直都會 call 到 class A 的版本。而在 late binding 的情況下,
要 call 的 function 的位址在 runtime 決定,會從 virtual table
中找到對應的 function 的位址,
所以可以 call 到各自的版本。
C++11 - override & final
override
override
是提供給繼承的 class 用的,目的是確保 function 有 override 到 base class 的 virtual funcion,
標上 override
後,compiler 可以在 compile time 的時候檢查是否真的有 override,
可以避免不小心沒寫好造成該 override 的 function 沒有 override 到。
class A
{
public:
virtual void foo();
void bar();
};
class B : A
{
public:
void foo() const override; // Error: B::foo does not override A::foo
// (signature mismatch)
void foo() override; // OK: B::foo overrides A::foo
void bar() override; // Error: A::bar is not virtual
};
final
final
是提供給 class 或 base class 的 virtual function 使用的,
標上 final
的 class 不能再被繼承,標上 final
的 virutal function 不能再被 override。
class A
{
public:
virtual void foo() final; // A::foo is final
void bar() final; // Error: non-virtual function cannot be final
};
class B final : A // struct B is final
{
public:
void foo(); // Error: foo cannot be overridden as it's final in A
};
class C : B // Error: B is final
{
};