по спецификатору защищенного доступа.

ример кода, который меня раздражает:

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' */
    }
};

Как вы получаете доступ к защищенной переопределенной функции?

Спасибо за вашу помощь. : О)

 underscore_d13 окт. 2018 г., 21:02
C ++ называет их функциями-членами, а не методами (хотя некоторые люди используют последние, но по моему опыту это приводит только к лингвистическим аргументам), и понятия одинаковы для функций-членов и переменных-членов, поэтому: дубликатДоступ к защищенным членам в производном классе
 GWW12 янв. 2011 г., 19:26
Я не думаю, что ваша реализация совершенно правильная. Почему у вас есть экземпляр Base в качестве переменной-члена? this-> b-> foo () будет пытаться вызвать чисто виртуальный метод.
 34100812 янв. 2011 г., 19:34
Эта программа не должна компилироваться. Вы не можете создать экземпляр абстрактного класса ....b указывает на экземпляр какого-то другого класса, полученного изBase.
 user20272913 окт. 2018 г., 09:21
Смотрите такжеstackoverflow.com/questions/3247671/... (это о членах вместо методов, но они не очень разные)
 Bernard Rosset13 янв. 2011 г., 11:44
Я опустил точность: атрибут Derived :: b предназначен для хранения любого экземпляра производных классов из Base

Ответы на вопрос(6)

Решение Вопроса


Таким образом, вам разрешено звонитьthis->foo(), но вы не можете звонитьthis->b->foo(), Это не зависит от того,Derived обеспечивает реализацию дляfoo или нет.

Причина этого ограничения заключается в том, что в противном случае было бы очень легко обойти защищенный доступ. Вы просто создаете класс, какDerivedи вдруг у вас также есть доступ к частям других классов (например,OtherDerived) которые должны были быть недоступны для посторонних.

 underscore_d13 окт. 2018 г., 21:00
верно, речь идет не о «безопасности», а о том, чтобы сообщить пользователям, какие части класса они могут использовать и на которые они могут положиться (то есть, какие части не являются деталями реализации, которые могут исчезнуть / измениться в любой момент). конечно, они не должны читать эти вещи, и им придется использовать акробатику с такими вещами, какoffsetof чтобы сделать это, но это определенно не о безопасности в смысле физического предотвращения доступа к данным - только документирование предполагаемого использования, семантики и стабильности API.
 Bernard Rosset13 янв. 2011 г., 11:47
Спасибо, теперь я четко понимаю причины ограничения ... Это была бы дыра в безопасности ... большая!
 DrYap06 апр. 2014 г., 22:25
Пожалуйста, не думайте об этом как о дыре в безопасности. Модификаторы доступа не обеспечивают никакой безопасности, вы можете просто прочитать ячейку памяти, если хотите получить данные.

Base который перенаправляет вызов к закрытой / защищенной функции (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 является виртуальным или нет, или является ли он частным или защищенным.

Вот это ссылка на работающую версию кода выше иВот другая версия той же идеи с немного большей бизнес-логикой.

--- откуда?

Вы можете получить доступ к защищенному члену только через наследование (кроме методов того же класса). Скажем, например, у вас естьclass Derived1 который наследует отDerivedзатем объектыDerived1 может позвонитьfoo().

РЕДАКТИРОВАТЬ:Статья MSDN по спецификатору защищенного доступа.

Base::foo(), который ссылается на базовый класс текущего экземпляра.

Однако, если ваш код должен делать это так, как вы пытаетесь, и это не разрешено, то вам нужно либо сделать foo () общедоступным, либо сделать Derived другом Base.

и (Base :: foo ()). Но в этом случае базовый класс не определяет foo (это чисто виртуальный), поэтому на самом деле нет функции, которую нужно выполнить, когда вы говоритеthis->b->foo(); поскольку b является указателем на Base, а не Derived.

 Gemini1412 янв. 2011 г., 19:46
@Jonathan Wood Я понимаю, что вы говорите, но, исходя из кода, который он опубликовал, похоже, что он пытается создать экземпляр абстрактного базового класса (Base) и вызвать чисто виртуальную функцию (Base :: foo ()), которая это нет-нет (как GWW и 341008 также упоминалось выше).
 Jonathan Wood12 янв. 2011 г., 19:36
Но код OP не ссылается на базовый класс текущего экземпляра. Он обращается к другому экземпляру, который предположительно является производным классом, который реализует чисто виртуальную функцию. (В противном случае экземпляр не может быть создан.)

но с классами, которые вы определили здесь, это не сработает?

virtual void foo2() {
  reinterpret_cast<Derived *>(this->b)->foo(); 
}

Reinterpret_cast указывает на VTABLE для базового объекта и вызывает его через этот метод доступа членов.

Ваш ответ на вопрос