Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer to a member function in an inaccessible base

The compilation of the next example :

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)();
}

fails with next errors :

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

I understand that the A is not accessible base of B, but I am using the using keyword. Shouldn't it allow the access to the function foo?

What are relevant paragraphs in the standard that prevents the above to be compiled?

like image 453
BЈовић Avatar asked Sep 15 '11 07:09

BЈовић


2 Answers

Since foo in B is inherited from A, &B::foo is identical to &A::foo, and has type void (A::*)(). When you write

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

you are trying to convert from void (A::*)() to void (B::*)(). Since B inherits privately fromA you cannot do that.

like image 76
ymett Avatar answered Nov 19 '22 08:11

ymett


Access to members of A is governed by chapter 11 "Member Access Control", but pointer-to-member conversions are covered by 4.11. In particular, 4.11/2 states that you can't convert a T A::* to an T B::* when you can't convert an B* to a A*.

Here's a slight variation of the question:

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);
}

We're still talking about the same function. It's not the name lookup of B::foo that fails (using takes care of that), it's the fact that the type of B::foo is void A::*() which cannot be converted to void B::*().

like image 29
MSalters Avatar answered Nov 19 '22 06:11

MSalters