Skip to main content
GameDev.net gamedev.net
🔒 Locked

c++ private inheritance question

Started by Samith Feb 9, 2011 at 5:43 AM 2 replies 2k views
Original Post
Samith
Samith

#include <iostream>

class base {
};

class derived : base {
};

class final_derived : public derived {
base *m_parent; // this line generates error c2247
public:
};

int main(int argc, const char *argv[])
{
printf("wtf\n");
return 0;
}


This code does not compile, giving me this error:
error C2247: 'base' not accessible because 'derived' uses 'private' to inherit from 'base'

My understanding of private inheritance is simply that only the derived class gets to treat itself as an instance of the privately inherited base class. In the case I have presented above, that would mean "final_derived" does not get to know that "derived" is also a "base," and it does not get to access any of "base's" members.

I do not however understand why "final_derived" is not allowed to have ANY REFERENCE to the type which "derived" is inherited from ("base"). I'm not trying to access anything, I just have a pointer! I could understand if I was like "m_parent = this" because I would be trying to access a conversion which isn't available to me, but I'm not doing that. I just want a reference to a "base". I don't see what access rules I'm violating!

EDIT: After googling my error code I've discovered that if I define m_parent as an instance of "::base *" instead of "base *" I don't get the error. This leads me to believe that when I declare an instance of a certain type, I must first look in my class namespaces for that type, then up through my derived classes, etc. In my case I must be finding the type "base" in the namespace of the class "derived", but it is a private type, so "final_derived" does not have access to it, and I must explicitly declare my pointer as a "::base *" to avoid the namespace confusion. Is this correct?

If this is what's happening, then it's weird that base classes are treated as member types in the classes that derive from them.
Hodgman
Hodgman
I don't have an explanation, but here's a work-around:typedef base base_t;
class final_derived : public derived
{
base_t *m_parent;
public:
};
Zao
Zao
Long story short, name lookup rules do not care about access. Only after a name is found is the access considered, and then it's too late to do anything about that the name is unusable. If you want to refer to the type, either qualify it explicitly or consider using protected inheritance (which I believe will be sufficient to provide access to the typename).

One interesting thing about this kind of lookup is that MSVC10 will allow your use of a private base in a class template, but Intel 12.0 will not. If you want to be portable, you should therefore qualify typenames that occur in a base.
To make it is hell. To fail is divine.
Samith
Samith
Good responses! I've looked up class name injection but can't find much on it, so I don't really know what the purpose of it is. But at least I know WHY my code doesn't compile. Thanks, guys!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.