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

#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; } 

我想也许只有这个被保护的成员可以被使用,并且被保护的其他实例的成员永远是不可达的。

但:

 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 } }; 

我觉得有点恶心,因为我一直在用C ++编程一段时间,但我找不到任何解释这种行为。

编辑:

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

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

EDIT2:

看来,当涉及到访问权时,根本不在使用什么样的类。

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

尽pipeC ++中的访问控制是基于每个类(而不是每个实例)进行的,但protected访问指定符却有一些特殊性。

语言规范希望确保您正在访问属于派生类的某个基本子对象的受保护成员。 你不应该能够访问一些不相关的基types的独立对象的受保护的成员。 特别是,您不能访问基础types的独立对象的受保护成员。 您只能访问作为基础子对象embedded到派生对象中的基础对象的受保护成员。

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

这意味着在你的例子中,受保护的成员somethingProtected()不能通过Base对象, Base *指针或Base &引用访问,但是可以通过Derived对象, Derived *指针和Derived &引用访问。 您的plainProtected somethingProtected()访问是允许的,因为它只是this->somethingProtected()的简写forms, thisDerived *types的。

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

注意按照上面的规则

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

第一次调用也会失败,而第二次调用将会失败,即使两者都试图访问相同的实体。

我相信你对如何访问基类成员有一些困惑。 只有这样:

 class Derived : public Base void drivedMethod() { Base::baseMethod(); } 

在你的例子中,你正试图访问另一个实例的受保护的成员。

一个Derived实例将有权访问它自己的受保护成员,但不能访问另一个受保护成员的类实例,这是通过devise。

事实上,访问其他类的保护成员,从另一个实例成员或主函数访问实际上都在公共访问…

http://www.cplusplus.com/doc/tutorial/inheritance/ (查找访问说明符表以查看不同级别)

两个例子都certificate了同样的事情,例如:

 void somethingDerived(Base& b) { b.somethingProtected(); // This does not 

在这里你的派生类获取b作为参数,所以它获得另一个基地的实例,然后因为b.somethingProtected不公开,它不会complie ..

这将会包括:

 void somethingDerived() { Base::somethingDerived(); 

你的第二个例子符合很好,因为你正在访问另一个d类的公共方法

 > void somethingDerived(Base& b) > { > b.somethingProtected(); // This does not > } 

Derived类只能访问Derived对象中受保护的基本成员。 它不能访问不是(必然) Derived对象的对象中的成员。 在失败的情况下,您尝试通过Base &访问成员,并且由于这可能引用了非Derived的对象,因此无法访问。

你所做的在C ++中是非法的。 受保护的成员不能被类的对象访问。 只有成员函数才能访问保护成员。 protected成员的行为就像私有成员,除非由派生类inheritance。 考虑下面给出的scheme,了解私人,公共和受保护成员之间的区别。

 class Base { private: void somethingPrivate() { std::cout << "sasa" << std::endl; } public: void somethingPublic() { std::cout << "haha" << std::endl; } protected: void somethingProtected() { std::cout << "lala" << std::endl; } }; class Derived : public Base { public: void somethingDerived() { Base b; b.somethingPublic(); // Works fine. somethingProtected(); // This is also fine because accessed by member function. //b.somethingProtected(); // Error. Called using object b. //somethingPrivate(); // Error. The function is not inherited by Derived. } };