C ++ protected:无法从派生类中访问库的受保护成员 [英] C++ protected: fail to access base's protected member from within derived class

查看:746
本文介绍了C ++ protected:无法从派生类中访问库的受保护成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

诚然,这个问题标题听起来与你邻居迈克反复提出的问题完全一样。我发现相同的几个问题的措辞是一样的,但没有一个是我的问题。



首先,我想澄清几点此问题的上下文:



1,c ++访问控制基于类基础而不是基于实例。因此,以下代码完全有效。

  class Base 
{
protected:
int b_;

public:
bool IsEqual(const Base& another)const
{
return another.b_ == b_; //访问另一个实例的protected成员
}
};

2,我完全明白为什么下面的代码无效 - 另一个可以是兄弟的实例。 / p>

  class Derived:public Base 
{
public:
//来纠正问题,更改基本&衍生&
bool IsEqual_Another(const Base& another)const
{
return another.b_ == b_;
}
};

现在要卸载我真正的问题:



假设在Derived类中,我有一个Base实例的数组。因此,有效地,Derived IS A Base(IS-A关系)和Derived由Base(复合关系)组成。我从某个地方读到这个(指的是IS-A和Has-A的设计)是一种设计的气味,我从来不应该有这样的场景。那么,例如,分形的数学概念可以通过IS-A和Has-A关系来建模。

  class Derived:public Base 
{
protected:
Base base_;

public:
bool IsEqual_Another(const Derived& another)const
{
return another.b_ == b_;
}

void TestFunc()
{
int b = base_.b_; // fail here
}
};

错误消息已经非常清楚地说明了错误,因此无需在您的答案中重复:


Main.cpp:140:7:error:'int Base :: b_'is protected
int b_;
^
Main.cpp:162:22:错误:在此上下文中
int b = base_.b _;


真的,根据以下2个事实,上面的代码应该工作:



1,C ++访问控制工作在类基础上,因此,请不要说我只能访问Derived的b_;我不能访问一个独立的Base实例的受保护的成员 - 它是在类基础上)。



2 ,错误消息说在这个上下文中 - 上下文是Derived(我试图从Derived中访问Base实例的受保护成员,它是受保护成员的一个特征 - 它应该能够从Base或任何那么为什么编译器会给我这个错误呢?

解决方案


2,错误消息说在这个上下文 - 上下文是Derived(我试图从Derived内访问Base实例的受保护成员。这是受保护成员的特征 - 它应该能够从Base内部或从Base派生的任何东西中访问。


,不得不去为这一个标准。



所以你问,为什么不可能?答案:因为标准如何定义受保护的成员访问:


§11.4
受保护成员访问



[1]
当非静态数据
成员或非成员访问时,应用超出前面第11节所述的附加访问检查-static成员函数是其命名类的受保护成员...如前所述
,授予对受保护成员的访问,因为引用发生在某个类C的朋友或成员


(强调我的)



看看是什么。

  class Base 
{
protected:
int b_;

public:
bool IsEqual(const Base& another)const
{
return another.b_ == b_; //访问另一个实例的protected成员
}
};

没问题。 another.b _ Base :: b _ ,我们正在从成员函数 Base :: IsEqual(const Base&)const

  class Derived:public Base 
{
public:
//来纠正问题,更改Base&衍生&
bool IsEqual_Another(const Base& another)const
{
return another.b_ == b_;
}
};

这里,我们访问 Base :: b _ 再次,但我们的上下文是一个成员函数 Derived :: IsEqual_Another(const Base&)const ,它不是 / code>。



 派生的:public Base 
{
protected:
Base bases_ [5];

public:
bool IsEqual_Another(const Derived& another)const
{
return another.b_ == b_;
}

void TestFunc()
{
int b = bases_ [0] .b_; // fail here
}
};

bases_ [0] .b _ Derived :: TestFunc()的上下文中的受保护的 Base :: b _ (或朋友...) Base



所以看起来编译器是按照规则。


Admittedly, this question title sounds pretty much exactly the same as the question you neighbour Mike has repeatedly asked. I found quite a few questions worded the same way, but none was what my question is about.

First of all, I'd like to clarify a few points for the context of this question:

1, c++ access control works on a class basis rather than instance basis. Therefore, the following code is completely valid.

class Base
{
protected:
    int b_;

public:
    bool IsEqual(const Base& another) const
    {
        return another.b_ == b_; // access another instance's protected member
    }
};

2, I completely understand why the following code is NOT valid - another can be a sibling instance.

class Derived : public Base
{
public:
    // to correct the problem, change the Base& to Derived&
    bool IsEqual_Another(const Base& another) const
    {
        return another.b_ == b_;
    }
};

Now time to unload my real question:

Assume in the Derived class, I have an array of Base instances. So effectively, Derived IS A Base(IS-A relation), and Derived consists of Base(Composite relation). I read from somewhere that this(refers to the design of both IS-A and Has-A) is a design smell and I should never have a scenario like this in the first place. Well, the mathematical concept of Fractals, for example, can be modelled by both IS-A and Has-A relations. However, let's disregard the opinion on design for a moment and just focus on the technical problem.

class Derived : public Base
{
protected:
    Base base_;

public:
    bool IsEqual_Another(const Derived& another) const
    {
        return another.b_ == b_;
    }

    void TestFunc()
    {
        int b = base_.b_; // fail here
    }
};

The error message has already stated the error very clearly, so there's no need to repeat that in your answer:

Main.cpp:140:7: error: ‘int Base::b_’ is protected int b_; ^ Main.cpp:162:22: error: within this context int b = base_.b_;

Really, according to the following 2 facts, the code above should work:

1, C++ access control works on class basis rather than instance basis(therefore, please don't say that I can only access Derived's b_; I can't access a stand alone Base instance's protected members - it's on class basis).

2, Error message says "within this context" - the context is Derived(I was trying to access a Base instance's protected member from within Derived. It's the very feature of a protected member - it should be able to be accessed from within Base or anything that derives from Base.

So why is the compiler giving me this error?

解决方案

2, Error message says "within this context" - the context is Derived(I was trying to access a Base instance's protected member from within Derived. It's the very feature of a protected member- it should be able to be accessed from within Base or anything that derives from Base.

Okay, had to go to the standard for this one.

So you're asking, "Why isn't it possible?" The answer: Because of how the standard really defines protected member access:

§ 11.4 Protected member access

[1] An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class...As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C.

(emphasis mine)

So let's go over your examples to see what's what.

class Base
{
protected:
    int b_;

public:
    bool IsEqual(const Base& another) const
    {
        return another.b_ == b_; // access another instance's protected member
    }
};

No problem. another.b_ is Base::b_, and we're accessing it from a member function Base::IsEqual(const Base&) const.

class Derived : public Base
{
public:
    // to correct the problem, change the Base& to Derived&
    bool IsEqual_Another(const Base& another) const
    {
        return another.b_ == b_;
    }
};

Here, we're accessing Base::b_ again, but our context is a member function Derived::IsEqual_Another(const Base&) const, which isn't a member of Base. So no go.

Now for the alleged culprit.

class Derived : public Base
{
protected:
    Base bases_[5];

public:
    bool IsEqual_Another(const Derived& another) const
    {
        return another.b_ == b_;
    }

    void TestFunc()
    {
        int b = bases_[0].b_; // fail here
    }
};

bases_[0].b_ is accessing the protected Base::b_, inside the context of Derived::TestFunc(), which isn't a member (or friend...) of Base.

So looks like the compiler is acting in accordance with the rules.

这篇关于C ++ protected:无法从派生类中访问库的受保护成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆