2012-02-04 139 views
2

http://www.parashift.com/c++-faq-lite/basics-of-inheritance.html#faq-19.5如何訪問派生類中的受保護成員?

甲構件(無論數據成員或成員函數)中的一類受保護的節中聲明只能由成員函數和該類的朋友訪問,並且通過成員函數和派生類的朋友

那麼,在派生類中訪問受保護函數fun的方法是什麼?

#include <iostream> 
using namespace std; 

class X 
{ 
    private: 
     int var; 
    protected: 
     void fun() 
     { 
      var = 10; 
      cout << "\nFrom X" << var; 
     } 
}; 

class Y : public X 
{ 
    private: 
     int var; 
    public: 
     void fun() 
     { 
      var = 20; 
      cout << "\nFrom Y" << var; 
     } 

     void call() 
     { 
      fun(); 

      X objX; 
      objX.fun(); 
     } 
}; 

這導致:

[email protected]:~/> g++ type.cpp 
type.cpp: In member function ‘void Y::call()’: 
type.cpp:9:8: error: ‘void X::fun()’ is protected 
type.cpp:32:14: error: within this context 

我看到了這一點:Accessing protected members in a derived class

考慮:

你只能訪問受保護的成員(或 你的類型的實例衍生從你的類型)。您無法訪問父代或表親類型的實例的受保護成員。

就你而言,Derived類只能訪問派生實例的b成員,而不是其他Base實例。

更改構造函數以獲取派生實例也將解決 的問題。

如何在不更改構造函數聲明的情況下實現這一點?

回答

4

我認爲你正在做應該的東西看起來是這樣的:

#include <iostream> 
using namespace std; 

class X 
{ 
    private: 
     int var; 
protected: 
    virtual void fun() 
    { 
     var = 10; 
     cout << "\nFrom X" << var; 
    } 
}; 

class Y : public X 
{ 
private: 
    int var; 
public: 
    virtual void fun() 
    { 
     var = 20; 
     cout << "\nFrom Y" << var; 
    } 

    void call() 
    { 
     fun(); 


     X::fun(); 
    } 
}; 

這樣,你可以從你的基類中調用隱伏成員。否則,您必須添加朋友X,因爲它在其他帖子中被指出。

+0

+1。是。 X :: fun()是從基類X訪問隱藏名稱的方式。不需要朋友或臨時對象。 – 2012-02-04 11:10:41

+2

這是一個完全不同的用例。這是在'* this'上調用'X :: fun',而不是在類型'X'的對象上調用它,而不是'Y'對象的基類,這個對象正在嘗試這個問題。 – 2012-02-04 12:48:42

+0

我不明白這可以被接受爲答案,就像@CharlesBailey說的那樣,這是一個完全不同的用例。 – Neutrino 2016-04-15 13:24:52

5

一種解決方案是增加friend class Y爲X.

1

在無效Ÿ::()調用

X objX; 
    objX.fun(); 

//這裏你試圖訪問物objx的保護成員,this /電流對象Y不包含objX作爲基礎對象,它們都是不同的對象。這就是爲什麼你不能訪問其成員。

作爲@anycom所告知的解決方案,您可以將Y的朋友作爲X的朋友。

編輯:我的意思是,從內Y(從X繼承),你可以簡單地調用保護/的公共成員「它的」基類X即你訪問它的基礎件簡單。但是,這並不意味着您現在可以訪問類型爲X的所有對象的受保護成員,因爲您試圖訪問類X的外部作用域中的成員,即通過X的對象訪問這些成員。你知道所有這些規則,但它似乎你做了太多的思考0_o

+0

'Y的this/current對象不包含objX,因爲它是基礎對象'該語句的含義是什麼? – 2012-02-04 10:41:40

+0

@AnishaKaul每個對象都有一個指向'this'的指針,就像你已經知道的那樣。 X是Y的基類,那麼Y的對象將包含類「X」的子對象。在你的代碼中,'Y'具有基類「X」,它可以在'Y'範圍內訪問**基類**'X' **的protected/pubic成員,但不能訪問任何保護/對象'X'(你在你的代碼中創建)的私有成員,就像你不能從'main'訪問私有成員'Y'一樣 – 2012-02-04 15:14:14

+0

@AnishaKaul請閱讀:http://msdn.microsoft.com/ en-us/library/x9wzb5es%28v = vs.80%29.aspx – 2012-02-04 15:24:05

-1

你沒有訪問你的派生類中的保護函數,你試圖超載它,並從保護提升到公共。這是禁止的操作,您只能隱藏派生類中的函數,例如過載保護功能作爲私人使用。

訪問保護功能是指一類的一些成員稱之爲:

class Y : public X 
{ 
public: 
    void call() { 
     fun(); 
    } 
} 

或像你通過objX.fun();調用它也是正確的。

1

見這個例子:

#include <iostream> 
using namespace std; 

class X { 
    private: 
    int var; 
    protected: 
    void fun() 
    { 
     var = 10; 
     cout << "\nFrom X" << var; 
    } 
}; 

class Y : public X { 
    private: 
    int var; 
    public: 
    void fun() 
    { 
     var = 20; 
     cout << "\nFrom Y" << var; 
    } 

    void call() 
    { 
     fun(); /* call to Y::fun() */ 
     X::fun(); /* call to X::fun() */ 

     X objX; 
     /* this will not compile, because fun is protected in X   
     objX.fun(); */ 

    } 
}; 

int main(int argc, char ** argv) { 
    Y y; 
    y.call(); 
    return 0; 
} 

這就產生

 
From Y20 
From X10 

因爲你Y中重載fun() - 方法,你必須給編譯器的提示哪一個你的意思是,如果你想通過調用X::fun()來調用X中的fun -method。

1

好吧,如果friend是確定的,那麼這個角度也可以被確定:

#include <iostream> 

class X { 
private: 
    int var; 
protected: 
    virtual void fun() { 
     var = 10; 
     std::cout << "\nFrom X" << var; 
    } 

    static void Fun(X& x) { 
     x.fun(); 
    } 
}; 

class Y : public X { 
private: 
    int var; 
public: 
    virtual void fun() { 
     var = 20; 
     std::cout << "\nFrom Y" << var; 
    } 

    void call() { 
     fun(); 
     X objX; 
     objX.fun(); /* << ne-ne */ 
     Fun(objX); /* << ok */ 
    } 
}; 

當然,如果你使用這個銘記傳遞給X::Fun類型的原樣。