2016-03-27 157 views
2

我正在嘗試一個小例子來實踐繼承和多態的概念。這裏是我的代碼的簡化版本:C++ - 訪問基類的受保護/私有成員

class Shape { 
protected: 
    int length; 
    int width; 
public: 
    virtual void setLength(int l) = 0; 
    virtual void setWidth(int w) = 0; 
}; 

class Rectangle : public Shape { 
public: 
    Rectangle(int l, int w) 
    : length(l), width(w) 
    { } 

    void setWidth(int w) { width = w; } 
    void setLength(int l) { length = l; } 
}; 

int main() { 
    Rectangle r(0,0); 
} 

我試圖運行上述程序。然而,當我編譯rectangle.cc,我收到以下錯誤

g++ -c rectangle.cc 

rectangle.cc: In constructor 'Rectangle::Rectangle(int, int)': 
rectangle.cc:13:5: error: class 'Rectangle' does not have any field named 'length' 
rectangle.cc:13:16: error: class 'Rectangle' does not have any field named 'width' 

據我瞭解,在公有繼承,基類的保護成員成爲派生類的保護成員,應該能夠到E像訪問公衆成員。那是不正確的?另外,如果長度和寬度都是基類的私有成員,那麼代碼將如何修改呢?

+0

如果減少這一個[MCVE]所以這將有助於錯誤更容易看到。你發佈的大部分代碼都是不相關的。 – juanchopanza

+0

@Q_A爲了讓您對我們的意思最小化有所認識,我將您的代碼縮減爲只有二十幾行重現相同錯誤的代碼。我希望你不介意。請注意,許多函數與您遇到的問題無關,也不需要創建一個「Shape」數組來重現它,等等。 – Barry

+0

謝謝,我會記住這一點 –

回答

3

就我的理解,在公共繼承中,基類的受保護成員成爲派生類的受保護成員,並且應該能夠像公共成員一樣訪問。那是不正確的?

這是主要是是真的。基類的公共和受保護的成員可以在派生類中訪問(public繼承在這裏不重要 - 隻影響外部觀察者的訪問)。但是,任何訪問類的成員只能在初始化在他們自己的類。在這種情況下,只有Shape可以初始化lengthwidth - 無關緊要,它們是protected,如果它們是publicprivate,它們也是如此。

你將不得不添加一個構造函數來做到這一點,你的Rectangle構造函數可以簡單地委託給。此作品無論lengthwidth的訪問控制(只要Shape構造函數是publicprotected):

struct Shape { 
    Shape(int l, int w) : length(l), width(w) { } 
}; 

struct Rectangle { 
    Rectangle(int l, int w) : Shape(l, w) { } 
}; 

或者,完整性,你可以只給它們,但肯定更喜歡有Shape初始化它們。此外,如果成員這隻作品中的問題是publicprotected

Rectangle(int l, int w) { 
    length = l; 
    width = w; 
} 

請注意,您setWidth()setLength()功能都很好 - 你訪問這些保護成員Rectangle的成員函數。只是不用於初始化。

+0

謝謝。如果長度和寬度都是基類的私有成員,代碼如何更改? –

+0

@Q_A讓'Shape'初始化其自己的成員意味着訪問控制無關緊要。然而,在那種情況下,setWidth()和setLength()是虛擬的並不合理 - 派生類實際上不能設置任何東西。 – Barry

2

不,基類的受保護成員不會成爲派生類的受保護成員。受保護的基類成員可以通過派生類訪問,與私有成員不同,它們在派生類的名稱空間中保持受保護(所以派生類的派生類也是如此)。

但是,基類的受保護成員仍然是基類的成員,而基類的構造函數仍然負責構造它們,而不是派生類的構造函數。

+0

實際上,編譯器錯誤是非常相關的。 –

+0

澄清:編譯器錯誤與「基類的受保護成員不成爲派生類的受保護成員」無關 – juanchopanza

+0

但是,如果基類的受保護成員可由派生類訪問,那麼爲什麼我會得到上面的錯誤?應該不能訪問長度和寬度? –

1

刪除零件:長度(l),寬度(w) 如果你想在派生類中使用長度和寬度(繼承),你可以直接使用它的名字。長度..完成...如果你碰巧在派生類中具有相同的命名字段「長度」,那麼使用派生類的「長度」使用this-> length ...

當繼承...公共訪問說明符聲明public使用受保護的...公衆和基類成爲受保護的保護,當類從基類成爲保護保護的派生類成爲大衆...