Указатель на функцию-член в недоступной базе - PullRequest
11 голосов
/ 15 сентября 2011

Компиляция следующего примера:

class A
{
  public:
    void foo()
    {
    }
};

class B : private A
{
  public:
    using A::foo;
};

int main()
{
    typedef void (B::*mf)();
    mf func = &B::foo;

    B b;
    (b.*func)();
}

завершается с ошибками:

main.cpp||In function ‘int main()’:  
main.cpp|18|error: ‘A’ is an inaccessible base of ‘B’  
main.cpp|18|error:    in pointer to member function conversion

Я понимаю, что A не является доступной базой B, но я используюusing ключевое слово.Разве он не должен разрешать доступ к функции foo?

Какие соответствующие параграфы в стандарте запрещают компиляцию вышеупомянутого?

Ответы [ 3 ]

6 голосов
/ 15 сентября 2011

Поскольку foo в B наследуется от A, &B::foo идентичен &A::foo и имеет тип void (A::*)().Когда вы пишете

typedef void (B::*mf)();
mf func = &B::foo;

, вы пытаетесь конвертировать из void (A::*)() в void (B::*)().Поскольку B наследуется в частном порядке от A, вы не можете этого сделать.

3 голосов
/ 15 сентября 2011

Доступ к элементам из A регулируется главой 11 "Контроль доступа к элементам", но преобразования указателя в элемент рассматриваются в 4.11. В частности, 4.11 / 2 гласит, что вы не можете преобразовать T A::* в T B::*, если вы не можете преобразовать B* в A*.

Вот небольшой вариант вопроса:

class A
{
  public:
    void foo()
    {
    }
};

class B : private A
{
  public:
    using A::foo;
};

int main()
{
    typedef void (A::*amf)();
    typedef void (B::*bmf)();
    amf func = &A::foo;
    bmf f2 = static_cast<bmf>(func);
}

Мы все еще говорим о той же функции. Не поиск по имени B::foo не удался (using позаботился об этом), это факт, что тип B::foo это void A::*(), который не может быть преобразован в void B::*().

0 голосов
/ 15 сентября 2011

Я упростил задачу.Основная проблема приведена ниже:

int main() 
{ 
    &B::foo; 
}

Здесь я пытаюсь получить доступ к адресу foo, который определен в классе A и унаследован в частном порядке.Поэтому он дает ошибку компиляции.

Использование только импортирует функцию.Он не меняет спецификатор доступа foo.

...