2016-11-16 91 views
6
#include <iostream> 

struct A 
{ 
    virtual void foo(){ std::cout << "A"; }; 
}; 

struct B : public A 
{ 
private: 
    void foo() override { std::cout << "B"; } 
}; 

int main() 
{ 
    A *p = new B; 
    p->foo();  // prints B 

// B b; 
// b.foo();  // error: foo is private 
    return 0; 
} 

// g++ -std=c++11 -Wall -Wextra -Wpedantic main.cpp && ./a.out 

所以我們可以調用B.foo()多態,但不是直接。當有人想要使用這種功能時,是否有任何用例?是否有用於私有公共虛擬方法的用例?

回答

2

它阻止您以非多態方式調用方法,這就是全部:使用範圍解析運算符直接訪問方法會導致難以維護代碼。在一個你並不是每個人都是經驗豐富的實現者(科學程序員可能會貢獻大代碼庫)的環境中,引入模式來保護你的代碼是值得的!

也就是說,Java明確禁止它,因爲他們認爲它是不好的風格。

+1

然後,Java不禁止什麼。 –

5

它的種類取決於基類的設計。假設你有一個基類

class Stream { 
public: 
    virtual bool canSeek() = 0; 
    virtual void seek(int offset) = 0; 
}; 

注:這個例子來自於.NET世界中,基類庫Stream類確實有這樣的虛擬財產CanSeek。我不想討論這是否是好設計,因爲我可以看到雙方的有效論據。這種基本類別實際存在就足夠了。現在

,派生類可以指定

class SpecificStream final : Stream { 
private: 
    virtual bool canSeek() { return false; } 
    virtual void seek(int offset) { throw "no seek for you"; } 
} 

在這個派生類,即seek在所有實施的事實,是因爲它在技術上需要。然而,處理這個SpecificStream的任何代碼已經知道seek函數對這個類完全沒用,不應該被調用。當針對基類Stream進行編碼時,僅在結果爲真時檢查canSeek()的結果並呼叫seek纔有意義。當針對SpecificStream類進行編碼時,檢查canSeek()是沒有意義的,因爲它的結果是靜態已知的,並且它絕對沒有意義調用seek()。如果這樣的調用是程序員錯誤,那麼可以幫助編譯器爲這種調用提供有用的消息。

相關問題