11

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?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • 4
    Good question. Because one can do `b.foo()`, but not `&B::foo`. – Maxim Egorushkin Sep 15 '11 at 07:32
  • Exact duplicate - [Function member pointer with private base](http://stackoverflow.com/questions/6942949/function-member-pointer-with-private-base). Not voting to close because the other question doesn't have an accepted answer, but [@Michael Burr's answer](http://stackoverflow.com/questions/6942949/function-member-pointer-with-private-base/6946317#6946317) seems like it should have been. – Eran Sep 15 '11 at 08:42
  • @eran, where have you been? I actually had to dig the spec and quote the exact same sentence again to convert the infidels! :-) – littleadv Sep 15 '11 at 08:44

3 Answers3

6

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.

ymett
  • 2,425
  • 14
  • 22
  • You could add that the following is correct: `typedef void (A::*mf)(); mf func = &B::foo;`, to insist on the fact that the issue regards pointer-to-member-function conversion and not accessibility. – Luc Touraille Sep 15 '11 at 09:48
  • @LucTouraille "_that the issue regards pointer-to-member-function conversion and not accessibility_" what do you mean? – curiousguy Dec 24 '11 at 04:41
3

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::*().

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    To make it even clearer: `void (A::*amf)() = 0; void (B::*bmf)() = amf;` fails on the second statement. – Maxim Egorushkin Sep 15 '11 at 08:46
  • I'm not sure I follow. In my answer I said that B::foo is used for overload resolution, and overload resolution only. For any other purpose its A::foo, and you claim that because its A::foo the assignment fails. Now, I would understand if you'd say that your answer completes my. But how is it 100% opposite, if its exactly the same? – littleadv Sep 15 '11 at 08:56
  • @litteadv: you claim, literally "you can do b.foo, but **not** &B::foo." I show that you **can**. See also http://ideone.com/LGphq. – MSalters Sep 15 '11 at 09:04
  • Regardless, I believe the user asked why using `using` doesn't solve the problem, you seem to not being able to address that. – littleadv Sep 15 '11 at 17:43
-1

I have simplified the problem. The main problem is given below:

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

Here I am trying to access the address of foo which is defined in class A and inherited privately. Therefore it is giving compilation error.

Using only imports the function. It does not change the access specifier of foo.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
sukumar
  • 131
  • 1
  • 7