为什么派生类不能在此代码中调用受保护的成员函数?

Mar*_*dik 63 c++ oop

#include <iostream>

class Base
{  
protected:
    void somethingProtected()
    {
        std::cout << "lala" << std::endl;
    }
};

class Derived : public Base
{
public:
    void somethingDerived()
    {
        Base b;
        b.somethingProtected();    // This does not compile
        somethingProtected();      // But this is fine
    }
};

int main()
{
    Derived d;
    d.somethingDerived();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想也许只有受保护的成员this可以使用,其他实例的受保护成员永远无法访问.

但:

class Derived : public Base
{
public:

    void somethingDerived(Derived& d)
    {
        d.somethingProtected();  // This compiles even though d is
                                 // potentially a different instance
    }

    void somethingDerived(Base& b)
    {
        b.somethingProtected();  // This does not
    }
};
Run Code Online (Sandbox Code Playgroud)

我觉得有点恶心,因为我已经用C++编程了一段时间,但是我找不到任何关于这种行为的解释.

编辑:

它是相同还是不同的实例无关紧要:

int main()
{
    Derived d1, d2;          // Two different instances
    d1.somethingDerived(d2); // This compiles fine
    d1.somethingDerived(d1); // This compiles fine
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

EDIT2:

似乎在访问权限时,根本使用的是什么类的实例并不重要:

class Base
{
public:
    void something(Base& b)  // Another instance
    {
        ++b.a;               // But can enter private members
    }

private:
    int a;
};
Run Code Online (Sandbox Code Playgroud)

AnT*_*AnT 75

尽管C++中的访问控制基于每个类工作(而不是基于每个实例),但protected访问说明符具有一些特殊性.

语言规范要确保您正在访问属于派生类的某个基础子对象的受保护成员.您不应该能够访问某些不相关的基类型独立对象的受保护成员.特别是,您无法访问基类型的独立对象的受保护成员.您只能访问作为基础子对象嵌入到派生对象中的基础对象的受保护成员.

因此,您必须通过pointer->member语法reference.memberobject.member语法访问受保护的成员,其中指针/引用/对象引用派生类.

这意味着在您的示例中,受保护的成员somethingProtected()不能通过Base对象,Base *指针或Base &引用访问,但可以通过Derived对象,Derived *指针和Derived &引用访问它.你的普通somethingProtected()访问是不允许的,因为它仅仅是一个速记this->somethingProtected()这里this是类型的Derived *.

b.somethingProtected() 违反了上述要求.

注意按照上面的规则

void Derived::somethingDerived()
{
    Base *b = this;
    b->somethingProtected();    // ERROR
    this->somethingProtected(); // OK
}
Run Code Online (Sandbox Code Playgroud)

即使两者都试图访问同一个实体,第一个调用也将失败而第二个调用将编译.

  • @YoungJohn:**11.4受保护的访问***表示当对受保护成员的引用*"发生在某个C类的朋友或成员中"*并通过*"a(可能是隐式的)对象表达式"*发生时,则*"对象表达式的类应为C或从C"*派生的类.在上面的例子中,访问发生在`Derived`的成员中.在第一次访问中,对象expresson是`*b`,而在第二次访问中它是`*this`.根据上述规则,第一次访问无效,第二次访问正常. (4认同)
  • 我理解这个规则.但是我不明白为什么它存在.调用其他基类对象的受保护成员的危害在哪里?使用虚函数时,这可能很有用. (2认同)