2011-01-22 116 views
9

我是C++新手,我有多年的OO語言經驗,如C/C#/ Objective-C。現在,我正在學習C++。C++子類訪問修飾符?

我看到這個C++代碼:

class World : public State 
    { 
    }; 

看來類World繼承的類State公開。 公共子類?這很難理解。

此功能的概念是什麼? 何時這是有用的或必需的?

+0

你是不是要寫`class World:private State {}`?在你實際寫的內容中,繼承是公開的。 – 2011-01-22 14:59:04

+0

您的意思是「世界級:私人國家」嗎? – detunized 2011-01-22 14:59:14

+0

@Steve,@detunized我很抱歉我的愚蠢的錯誤。我修改了這個問題。 – Eonil 2011-01-22 15:04:23

回答

13

public關鍵字的需求僅僅是對於使用關鍵字class定義的類的缺省訪問修飾符(對於所有內容(數據成員,成員函數和基類)而言)爲private。所以

class World : State {}; 

是一樣的:

class World : private State {}; 

而這可能不是你想要的東西 - 這意味着該基類是隻有類World中訪問。局外人「不知道」繼承是否存在。

對於關鍵字struct定義的類,默認的訪問修飾符是public,所以你寫:

struct World : State {}; 

和得到的東西,兩者的外觀和行爲有點像繼承所有其他語言。但是關鍵字struct以及它定義一個類的事實實際上只是爲了與C兼容。你不會找到許多推薦使用它的C++風格指南,只是爲了獲得默認的公共可訪問性 - 通常它只用於POD類,或者僅用於沒有成員函數的類。至於爲什麼C++首先具有私有繼承:對於大多數目的而言,私有繼承是一種組合形式。正常組成:

class World { 
    State state; 
    public: 
    void foo() { 
     state.bar(); 
     state.baz(); 
     and so on 
    } 
}; 

也就是說,World世界知道它是用一個國家來實現的,而外界並不知道World是如何實現的。

class World : private State { 
    public: 
    void foo() { 
     bar(); 
     baz(); 
     and so on 
    } 
}; 

也就是說,該類全世界都知道,它是由實施的國家,與外界不知道它是如何實現的。但是,您可以選擇性地公開州的部分界面,例如將using State::bar;放入世界定義的公共部分。效果就好像你在世界上費力地編寫了一個函數(或者幾個重載函數),每個函數都委託給State上的同一個函數。

但是,除了避免鍵入外,私有繼承的一個常見用途是類State爲空時,即沒有數據成員。然後,如果它是World的成員,它必須佔據一定的空間(誠然,取決於對象佈局,這可能是空間,否則將只是填充,所以它不一定會增加大小World),但是如果它是基類那麼一個叫做「空基類優化」的東西就會被踢進去,而且它可能是零尺寸的。如果你正在創建一個批次的對象,這可能很重要。私有繼承使優化成爲可能,但外部世界不會推斷出「是 - 是」的關係,因爲它看不到繼承。

這是一個非常好的區別 - 如果有疑問只是使用明確的組合。介紹繼承以節省打字是非常好的,直到它有一些意想不到的後果。

3

是什麼讓你覺得它是私密的?它表示公共權利在那裏,這意味着它是公開分類。除此之外,私有和受保護的繼承和公共繼承一樣,除了所有的成員變量都是函數都至少被私有或受保護的可訪問性繼承。例如,如果State有一個公共成員函數'foo()',它將在'World'中是私人的。

這在實踐中很少使用,但它確實有其目的。我見過的最常見的用途是通過繼承進行組合。即你想要一個「有一個」關係而不是一個「是一個」(你通常使用公有繼承來獲得)。通過私下繼承這個類,你得到了它的所有變量和方法,但是你不會將它暴露給外部世界。

使用私有繼承進行組合的一個優勢來自空基類優化(EBCO)。使用普通組合,具有空類的成員對象仍然會使用至少1個字節,因爲所有變量都必須具有唯一地址。如果你私下繼承了你想組成的對象,那麼這不適用,你不會遭受內存丟失。

例如

class Empty { }; 

class Foo 
{ 
    int foo; 
    Empty e; 
}; 

class Bar : private Empty 
{ 
    int foo; 
}; 

這裏,sizeof(Foo)將可能是5,但sizeof(Bar)會因爲空基類的4。

4

如果

class World: private State 
{ 
}; 

私有繼承意味着State所有publicprotected成員將由World被繼承和將成爲private。這在World內部密封State。沒有繼承自World的課程將能夠訪問State的任何功能。

0

祖先類名稱前面的public/protected/private關鍵字指示來自祖先的成員的期望可見性。對於私有繼承,後代只從祖先繼承實現,但不繼承接口。

class A { 
public: 
    void foo(); 
}; 

class B : private A { 
public: 
    void bar(); 
}; 

void B::bar() 
{ 
    foo(); // can access foo() 
} 

B b; 
b.foo(); // forbidden 
b.bar(); // allowed 

在一般情況下,你應該使用公有繼承,因爲繼承不應該被用於實現只重複使用(這是私有繼承一樣)。