2012-02-04 126 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类型的原样。