在C++11
中增加了override
的關(guān)鍵字践樱,當(dāng)子類需要覆寫基類的虛函數(shù)時(shí)忽洛,提供顯式的override
,可以有效改善程序的編譯時(shí)安全。
編譯時(shí)安全
例如饰躲,存在一個(gè)基類Test
丁寄,它聲明了2
個(gè)抽象方法屑埋。
struct TestResult;
struct Test {
virtual void run(TestResult&) = 0;
virtual int countTestCases() const = 0;
virtual ~Test() {}
};
在子類中覆寫基類抽象方法時(shí),顯式地標(biāo)注override
不僅可以增強(qiáng)代碼的可讀性,而且可以增強(qiáng)編譯時(shí)的安全性。如果嚴(yán)格遵循該規(guī)則洪鸭,當(dāng)重構(gòu)基類的抽象方法的簽名時(shí),編譯器可以準(zhǔn)確地找到所有編譯失敗的引用點(diǎn),提供了絕佳的重構(gòu)防護(hù)作用辖源。
#include "cut/core/test.h"
struct TestDecorator : Test {
TestDecorator(Test& test);
private:
void run(TestResult&) override;
int countTestCases() const override;
private:
Test& test;
};
按接口編程
「按接口編程」是面向?qū)ο蟮闹匾瓌t。遵守該原則坞嘀,不僅使得客戶代碼依賴于更加穩(wěn)定的抽象继准,而且縮小了所依賴的范圍,使得客戶與實(shí)現(xiàn)更加正交陈瘦,從而實(shí)現(xiàn)解耦皱埠。在C++語言中诀黍,訪問控制和多態(tài)覆寫行為是分離的也颤,子類是可以覆寫父類私有的虛函數(shù)的燥翅。例如,模板方法的模式的典型實(shí)現(xiàn)方法姐霍,都是覆寫基類的私有的虛函數(shù)實(shí)現(xiàn)的恨胚。
私有化覆寫的虛函數(shù)骂因,可以有效保證用戶錯(cuò)誤地調(diào)用子類覆寫的成員函數(shù),暗示用戶應(yīng)該基于抽象的接口類型實(shí)施編程页屠。例如,上例TestDecorator
的構(gòu)造函數(shù)必須公開镐捧,否則該類型的實(shí)例就不可構(gòu)造了玩焰。其覆寫的所有虛函數(shù)都被聲明為private
荤西,警示用戶應(yīng)該基于Test
在運(yùn)行時(shí)多態(tài)地調(diào)用相應(yīng)的抽象方法。
TestSuite: Test實(shí)例集的倉(cāng)庫(kù)實(shí)現(xiàn)
以TestSuite
為例冠句,它持有一系列Test
類型的實(shí)例轻掩,它們的運(yùn)行時(shí)類型可能是TestCase, TestSuite, TestDecorator
等等∨车祝基于抽象的Test
類型坠狡,實(shí)現(xiàn)用例集的隱式樹型結(jié)構(gòu)舀凛。
#include "cut/core/test.h"
#include "cut/core/internal/bare_test_suite.h"
#include <vector>
struct TestSuite : Test, private BareTestSuite {
~TestSuite();
void add(Test* test);
private:
void run(TestResult& result) override;
int countTestCases() const override;
private:
const Test& get() const override;
void runBare(TestResult& result) override;
private:
std::vector<Test*> tests;
};
TestSuite
在實(shí)現(xiàn)析構(gòu)函數(shù)及其其他函數(shù)時(shí),都是基于Test
的抽象類型實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)調(diào)用的。
#include "cut/core/test_suite.h"
#include "cub/base/algo.h"
void TestSuite::add(Test* test) {
tests.push_back(test);
}
TestSuite::~TestSuite() {
for (auto test : tests) {
delete test;
}
}
int TestSuite::countTestCases() const {
static auto accumulator = [](Test* test){
return test->countTestCases();
};
return cub::reduce(tests, 0, accumulator);
}
const Test& TestSuite::get() const {
return *this;
}
void TestSuite::runBare(TestResult& result) {
for (Test* test : tests) {
test->run(result);
}
}
void TestSuite::run(TestResult& result) {
result.runTestSuite(*this);
}
Test, TestSuite, TestCase, TestDecorator
之間的關(guān)系如下圖所示昧旨。