问题
Here is a sample of code that annoys me:
class Base {
protected:
virtual void foo() = 0;
};
class Derived : public Base {
private:
Base *b; /* Initialized by constructor, not shown here
Intended to store a pointer on an instance of any derived class of Base */
protected:
virtual void foo() { /* Some implementation */ };
virtual void foo2() {
this->b->foo(); /* Compilator sets an error: 'virtual void Base::foo() is protected' */
}
};
How do you access to the protected overrided function?
Thanks for your help. :o)
回答1:
Protected members in a base-class are only accessible by the current object.
Thus, you are allowed to call this->foo()
, but you are not allowed to call this->b->foo()
. This is independent of whether Derived
provides an implementation for foo
or not.
The reason behind this restriction is that it would otherwise be very easy to circumvent protected access. You just create a class like Derived
, and suddenly you also have access to parts of other classes (like OtherDerived
) that were supposed to be inaccessible to outsiders.
回答2:
Normally, you would do it using Base::foo()
, which refers to the base class of the current instance.
However, if your code needs to do it the way you're trying to and it's not allowed, then you'll need to either make foo() public or make Derived a friend of Base.
回答3:
One solution would be to declare a static protected function in Base
that redirects the call to the private / protected function (foo
in the example).
Lets say:
class Base {
protected:
static void call_foo(Base* base) { base->foo(); }
private:
virtual void foo() = 0;
};
class Derived : public Base {
private:
Base* b;
protected:
virtual void foo(){/* Some implementation */};
virtual void foo2()
{
// b->foo(); // doesn't work
call_foo(b); // works
}
};
This way, we don't break encapsulation because the designer of Base
can make an explicit choice to allow all derived classes to call foo
on each other, while avoiding to put foo
into the public interface or explicitly turning all possible subclasses of Base
into friends.
Also, this method works regardless of whether foo
is virtual or not, or whether it is private or protected.
Here is a link to a running version of the code above and here another version of the same idea with a little more business logic.
回答4:
It's a bit fragile, but with the classes you defined here, won't this work?
virtual void foo2() {
reinterpret_cast<Derived *>(this->b)->foo();
}
The reinterpret_cast points at the VTABLE for the base object, and calls it through this members accessor.
回答5:
You call base functions explicitly with the scope operator (Base::foo()). But in this case, the Base class doesn't define foo (it's pure virtual), so there's actually no function to execute when you say this->b->foo();
since b is a pointer to Base and not Derived.
回答6:
How do you access to the protected overrided function?
--- from where?
You can access a protected member only via inheritance (apart from the methods of the same class). Say for example you have a class Derived1
which inherits from Derived
, then objects of Derived1
can call foo()
.
EDIT: MSDN article on protected access specifier.
来源:https://stackoverflow.com/questions/4672438/how-to-access-protected-method-in-base-class-from-derived-class