可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Possible Duplicate:
cannot call base class protected functions?
I don't understand the following, when Derived inherits from Base, it gets access to its protected members which can be accessed through Derived functions. But if, Base class tries to access its own members from Derived class (which itself allows access to Base), it doesn't get access, why?
class Base { protected: int x; }; class Derived : Base { public: void foo(Base* b); }; void Derived::foo(Base* b) { b->x = 2; // cannot access protected member, // though Derived inherits from Base, why? }
回答1:
A common misunderstanding.
Inside Derived::foo(), you can access protected base members of objects of class Derived. However, *b is not of type Derived. Rather, it is of type Base, and so it does not have anything to do with your class.
It's a different matter if you take a Derived* as an argument -- then you will indeed have access to protected base members.
Let's spell it out:
struct Derived; struct Base { int f(Derived *); protected: int x; private: int y; }; struct Derived : public Base { int g(Base *); int h(Derived *); }; int Derived::g(Base * b) { return b->x; // error, protected member of unrelated class return b->y; // error, private member of different class } int Derived::h(Derived * d) { return d->x; // OK, protected base member accessible in derived class return d->y; // error, private member of different class } int Base::f(Derived * d) { return d->x; // OK, d converts to Base* return d->y; // OK, ditto }
回答2:
You ran smack dab into a special rule in the standard:
11.5 Protected member access
When a friend or a member function of a derived class references a protected nonstatic member function or protected nonstatic data member of a base class, an access check applies in addition to those described earlier in clause 11. Except when forming a pointer to member, *the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class).
One reason for this addition access check is with regard to the behaviors of those base class protected members. Since the members are protected, a different derived class can add semantics to or even make wholesale changes in the meaning of those derived members. (This is one of the reasons why protected data is rather dangerous.) Because your class is oblivious to these additions / modifications to the base class semantics made in other derived classes, the best thing to do is to preclude access to base class members when the access would be through the base class.
回答3:
You have the right idea, but you're not using the protected member correctly.
void foo(Base* b) should instead be void foo();
and its implementation would be:
void Derived::foo() { return this-> x; }
Because x is a protected member, you can't access it from another object -- even if that object inherits from that class. You can only access it from the derived object itself.
回答4:
To provide concrete example of what others are saying:
class Base { protected: int x; }; class Derived : Base { public: void foo(Derived*, Base*); }; int main() { Base fiddle; Derived fast, furious; fast.foo(&furious, &fiddle); } void Derived::foo(Derived *d, Base* b) { x = 1; // Legal, updates fast.x this->x = 2; // Legal, updates fast.x d->x = 3; // Legal, updates furious.x b->x = 4; // Error, would have updated fiddle.x }
回答5:
What you've essentially done is created an instance of base that has a different relation to derived than the internal instance of base inside of derived. Setting a variable to protected gives the inherited class access to it's own internal instance of base. However, creating an object of type base in the class is something different, and therefore, does not allow access.