Указатель на метод базового класса с защищенным наследованием - PullRequest
6 голосов
/ 16 мая 2019

У меня есть этот код:

class Foo
{
public:
    int x = 4;
    int & operator[](size_t index) { return x; }
};

class Bar : protected Foo
{
public: 
    using Foo::operator[];

    Bar () { x++; }
};

int main(int agrc, char ** argv)
{
    typedef int &(Bar::*getOp)(size_t index);

    Bar b;
    auto bVal = b[4];
    getOp o = &Bar::operator[]; 
    auto bVal2 = (b.*o)(7);
}

Однако я не могу скомпилировать это, потому что

ошибка C2247: «Foo» недоступен, поскольку «Bar» использует «protected» для наследования от «Foo»

Почему это невозможно, когда я использовал using и могу напрямую вызывать оператора? Есть ли способ обойти?

Если я изменяю наследование на общедоступное, оно работает.

Примечание: Это просто пример большего класса. Я не хочу использовать публичное наследование, потому что я не хочу иметь возможность делать Foo f = Bar(), потому что в Bar я скрываю родительские методы (я не использую виртуальный).

Ответы [ 2 ]

5 голосов
/ 16 мая 2019

Почему это невозможно, если я использовал с помощью оператора и могу напрямую вызывать оператора?

Объявление использования дает вам доступ к имени operator[]. Но это не меняет тип члена. Остается int &(Foo::*)(size_t). Обратите внимание на Foo.

Таким образом, преобразование в объявленный тип типа o требует преобразования вниз по дереву наследования. Это преобразование должно проверить, что целевой класс действительно получен из базы, но это недоступная база.

Один из способов обойти это - дать Bar функцию-член, которая возвращает этот указатель. Внутри области видимости Bar база будет доступна для конвертации. Кроме того, этот тип преобразования требует static_cast.

3 голосов
/ 16 мая 2019

Это преобразование не допускается, если базовый класс Foo недоступен.

Вместо использования using Foo::operator[], возможно, это может решить вашу проблему:

int& operator[](size_t index) { // now a Bar::operator[], not Foo:: anymore
    return Foo::operator[](index);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...