Как открыть защищенный метод базового класса из производного класса?
вот пример кода, который раздражает меня:
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' */
}
};
Как получить доступ к защищенной переопределенной функции?
Спасибо за помощь. : o)
6 ответов
защищенные члены в базовом классе доступны только текущему объекту.
Таким образом, вы можете позвонить this->foo()
, но вам не разрешается звонить this->b->foo()
. Это не зависит от того,Derived
обеспечивает реализацию foo
или нет.
причина этого ограничения заключается в том, что в противном случае было бы очень легко обойти защищенный доступ. Вы просто создаете класс, как Derived
, и вдруг у вас также есть доступ к частям других классов (как OtherDerived
), которые должны быть недоступны для посторонних лиц.
обычно вы делаете это с помощью Base::foo()
, который ссылается на базовый класс текущего экземпляра.
однако, если ваш код должен сделать это так, как вы пытаетесь, и это не разрешено, вам нужно либо сделать Foo() общедоступным, либо сделать производным другом базы.
одним из решений было бы объявить статическую защищенную функцию в Base
перенаправляет вызов на функцию private / protected (foo
в Примере).
допустим:
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
}
};
таким образом, мы не нарушаем инкапсуляцию, потому что дизайнер Base
можно сделать явный выбор, чтобы разрешить всем производным классам вызывать foo
друг на друга, избегая ставить foo
в открытый интерфейс или явное превращение всех возможных подклассов Base
в друзей.
кроме того, этот метод работает независимо от того,foo
виртуальная или нет, будет ли он закрытым или защищенным.
здесь является ссылкой на текущую версию кода выше и здесь другая версия той же идеи с немного большей бизнес-логикой.
это немного хрупко, но с классами, которые вы определили здесь, это не сработает?
virtual void foo2() {
reinterpret_cast<Derived *>(this->b)->foo();
}
reinterpret_cast указывает на VTABLE для базового объекта и вызывает его через этот метод доступа членов.
вы вызываете базовые функции явно с помощью оператора scope (Base::foo ()). Но в этом случае базовый класс не определяет foo (это чисто виртуальный), поэтому на самом деле нет функции для выполнения, когда вы говорите this->b->foo();
Так как b является указателем на Base и не производным.
как вы получаете доступ к защищенному функция перекрытая?
--- откуда?
вы можете получить доступ к защищенному члену только через наследование (кроме методов того же класса). Скажем, например, у вас есть class Derived1
, который наследует от Derived
, то объекты Derived1
можно назвать foo()
.
EDIT:статья MSDN на спецификаторе защищенного доступа.