I have the following hypothetical code:
class Base {
public:
virtual void print() {
std::cout << "Base\n";
}
// assume virtual destructor
};
class Derived : private Base {
public:
void print() {
std::cout << "Derived\n";
}
};
int main() {
// Derived d{}; works fine
Base *pd = new Derived{}; // doesn't work
pd->print();
// assume memory is deallocated
}
At first, I thought that it would work, because constructors aren't inherited anyways. But the compiler gives the error:
error: 'Base' is an inaccessible base of 'Derived'
And I'm not able to figure out what is really happening?
It's a good guess, but the problem isn't with constructors or member functions.
In the line
Base *pd = new Derived{}; // doesn't work
The compiler is implicitly converting the right side, new Derived{}, which is of type Derived*, to the type Base*.
The term that the standard uses to describe when one can implicitly convert a pointer to a derived class to a pointer to a base class is accessibility. From subsection 11.2/5:
If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class
There are a few technical conditions listed (11.2/4 if you really care) that can make a base class accessible, but Base meets none of these.
The short version is, private inheritance hides the base class and the access specifier private needs to be public for your code to compile. Hope that helps.
You are deriving Base privately, and that's why you are getting error.
With private inheritance, all members from the base class are inherited as private. This means private members stay private, and protected and public members become private. Thats why you are not able to use print()in main Compiler is not able to cast derived pointer to base type, because the inheritance is private.
In a context where the knowledge of the internals of the derived class is hidden (IE non-friend, not in a class derived from Derived) it seems like there is no relationship between the two classes.
When you try to assign to a pointer of the base type you are saying convert this Derived pointer to a Base pointer. As the inheritance is hidden, it is like you are trying to assign it to a pointer of an unrelated type. However the compiler does know that it is related, so rather than just giving you a unhelpful error, it tells you that the conversion that you are trying to do is inaccessible.
Related
A Base Class pointer can point to a derived class object. Why is the vice-versa not true?
That thread says that we can't make the derived class point to base class because the derived class may not have access to all the members of base class.
The same is true vice versa also.
The base class won't even have access to the members which are specific to derived classes.
#include <iostream>
using namespace std;
class BaseClass
{
public:
virtual void baseFx();
};
void BaseClass::baseFx()
{
std::cout << "From base virtual function\n";
}
class DerivedClass : public BaseClass
{
public:
void baseFx();
void h() { std::cout << "From derived class. h()\n"; }
};
void DerivedClass::baseFx()
{
std::cout << "From derived virtual function\n";
}
int main()
{
BaseClass* objBaseclassB = new DerivedClass();
objBaseclassB->baseFx (); // Calls derived class's virtual function.
objBaseclassB->h(); // error: 'class BaseClass' has no member named 'h'.
return 0;
}
So, why is the restriction only for derived class? Why is this not allowed considering the above logic?
DerivedClass* objBaseclassC = new BaseClass();
Assigning a Derived class object to Base class pointer is valid and the cornerstone of polymorphism.
Yes, the Derived class may have additional members which cannot be accessed via a base class pointer, which is okay because you, the programmer are doing such an assignment while being fully aware that you cannot access those members. You are doing it purely for the purpose of polymorphism. Which means you will only be calling virtual functions which will use the vtables to call the correct override based on which object the pointer is pointing to.
However, casting a base class pointer back to a derived class pointer is not straightforward. You need type information and it is only possible if the Base class is polymorphic (ie. has virtual functions) and the class you are casting to is derived from the Base class. This exact check is performed by dynamic_cast. dynamic_cast checks if the downcast is possible and returns the Derived class pointer if it is valid. Otherwise it returns nullptr.
Coming to your final question:
DerivedClass* objBaseclassC = new BaseClass(); is not valid because accessing any "extra" members in DerivedClass results in a crash.
But when you do
BaseClass* derivedPointer = new DerivedClass(); Such a construction will result in a compile time error.
Let me try and explain this in a logical way.
Inheritance in OO programming is used to implement an "is a" relationship between different classes. Eg. If there is a class Animal and a class Dog, we know a Dog "is an" Animal and hence Dog would extend Animal. Hence it would obviously exhibit a lot of functionality (eg. eat() - function) that is common amongst other animals (classes) say Horse. Thus, we tend to put such common code into the base class Animal and keep code specific to each sub-class in the derived classes. (Eg. bark() for Dog)
Hence, it only makes sense to allow a base class type pointer to point to a derived class object, ie,
Animal * horse1 = new Horse();
as after all a horse is an animal.
The other way around doesn't make sense as every Animal is not necessarily a horse.
PS: as far as C++ is concerned, inheritance is mainly just a re-use mechanism for common code.
I have a Base class pointer pointing to derived class object. The method foo() is public in base class but private in derived class. Base class foo() is virtual. So when i call foo() from Base class pointer, Vptr Table has the address of derived class foo(), BUT its private in Derived class ...so how is it getting called.??
I understand Run time polymorphism and i also understand that the Access specifiers work for compile time and Virtual concept works at run time. So there shall be No Compiler error.
My question is : Is this is a loop hole through which we can call private methods of Derived class ? or Its expected to behave this way.
Any good Explanation for this behavior.
Thanks a lot in advance.
CODE :
class A
{
public:
virtual void foo()
{
std::cout << "In A";
}
};
class B:public A
{
private:
void foo()
{
std::cout << "In B ??? Its Private Method :-( ";
}
};
int main()
{
A* ptr = new B();
ptr->foo();
return 0;
}
It's private method, but since it's virtual - it can be called.
n3690 11.5/1
The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by
the rules for a function that later overrides it.
Why this? Since
n3690 11.5/2
Access is checked at the call point using the type of the expression used to denote the object for which the
member function is called (B* in the example above). The access of the member function in the class in
which it was defined (D in the example above) is in general not known.
Access level is a compile-time concept. The runtime doesn't know if a method was declared private or public. Those are there for your convenience.
This is actually a good coding standard - a virtual method should be ideally public in the base class and private or protected in derived classes. This will force the caller to use the interfaces rather than the actual types (of course, this isn't always practical, but a good thing to take into account).
The concrete type is abstracted away in your case, as it should be. The base method is declared public and you're calling it through a pointer to a base, so it's allowed.
I have a Base class pointer pointing to derived class object. The method foo() is public in base class but private in derived class. Base class foo() is virtual. So when i call foo() from Base class pointer, Vptr Table has the address of derived class foo(), BUT its private in Derived class ...so how is it getting called.??
I understand Run time polymorphism and i also understand that the Access specifiers work for compile time and Virtual concept works at run time. So there shall be No Compiler error.
My question is : Is this is a loop hole through which we can call private methods of Derived class ? or Its expected to behave this way.
Any good Explanation for this behavior.
Thanks a lot in advance.
CODE :
class A
{
public:
virtual void foo()
{
std::cout << "In A";
}
};
class B:public A
{
private:
void foo()
{
std::cout << "In B ??? Its Private Method :-( ";
}
};
int main()
{
A* ptr = new B();
ptr->foo();
return 0;
}
It's private method, but since it's virtual - it can be called.
n3690 11.5/1
The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by
the rules for a function that later overrides it.
Why this? Since
n3690 11.5/2
Access is checked at the call point using the type of the expression used to denote the object for which the
member function is called (B* in the example above). The access of the member function in the class in
which it was defined (D in the example above) is in general not known.
Access level is a compile-time concept. The runtime doesn't know if a method was declared private or public. Those are there for your convenience.
This is actually a good coding standard - a virtual method should be ideally public in the base class and private or protected in derived classes. This will force the caller to use the interfaces rather than the actual types (of course, this isn't always practical, but a good thing to take into account).
The concrete type is abstracted away in your case, as it should be. The base method is declared public and you're calling it through a pointer to a base, so it's allowed.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++: overriding public\private inheritance
class base {
public:
virtual void doSomething() = 0;
};
class derived : public base {
private: // <-- Note this is private
virtual void doSomething()
{ cout << "Derived fn" << endl; }
};
Now if I do the following:
base *b = new derived;
b->doSomething(); // Calls the derived class function even though that is private
Question:
It's able to call the derived class function even though it is private. How is this possible?
Now if I change the inheritance access specifier from public to protected/private, I get a compilation error:
'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible
Note: I am aware of the concepts of the inheritance access specifiers. So in the second case as it's derived private/protected, it's inaccessible. But I wonder about the answer to first question. Any input will be highly appreciated.
Access control is implemented at compile time, not run-time, while polymorphism (including the use of virtual functions) is a run-time feature.
In the first case the access check is done (as it is always done) on the static type that the call is made through. The static type of *b is base, and in that case doSomething() is public.
C++03 11.6 "Access to virtual functions" says:
The access rules (clause 11) for a virtual function are determined by
its declaration and are not affected by the rules for a function that
later overrides it. [Example:
class B {
public:
virtual int f();
};
class D : public B {
private:
int f();
};
void f()
{
D d;
B* pb = &d;
D* pd = &d;
pb->f(); //OK:B::f()is public,
// D::f() is invoked
pd->f(); //error:D::f()is private
}
—end example]
Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.
Keep in mind especially that "the access of the member function in the class in which it was defined (D in the example above) is in general not known". In general, at the point in your example where b->doSomething(); is called, the compiler may have no knowledge at all about derived (or child), much less whether or not the access to derived::doSomething() is private.
Private functions are meant to be hidden from the outside world and from the derived classes. Although you are overriding the access specifier of the parent's DoSomething and making it private, you are instantiating a base class; so in the first case, you can call base's DoSomething as it is public. This scenario can be used if you want to stop people deriving from your derived class.
In the second case, the private access specifier causes the base's members not to be exposed to the users of the derived class, which effectively makes the derived class useless.
As far as I understand the reason that we cannot pass a derived class object to a base class reference for private inheritance is that Since Derived is privately inherited from Base, the default constructor of Base would be called before the constructor of Derived. But because it is private and not inherited to Derived, we get a compiler error.
But, if I try to create a public constructor for Base and inherit from Derived privately and then re-assign the public status to Base's constructor will it allow me to pass a derived's instance to Base reference?
I tried it as follows,
#include <iostream>
using namespace std;
class base
{
public:
base(){}
void print(){ puts("In base"); }
};
class derived : private base
{
public:
base::base; /* Throws an error - Declaration doesnt declare anything*/
void print(){ puts("In derived"); }
};
void func(base& bRef)
{
}
int main()
{
derived dObj;
func(dObj); /* Throws an error - 'base' is an inaccessible base of derived */
}
It throws an error for base::base (publicizing privately inherited constructor to public).
Is what I am trying valid? Can anyone please tell me?
The reason we cannot have a base class reference to a derived object that inherits privately is because that would violate the Liskov Substitution Principle: the derived object IS-NOT-A base class object because it does not provide the base class public interface. You cannot work around this
For this reason, private inheritance is a way of reusing implementation and not when you want to make a more specialized type. As this can most of the time be done with composition (i.e. having a member of the base class instead of privately deriving), private inheritance might be a bad code smell.
You can read here (be sure to follow all the links) for more information on when private inheritance is a good option (summary: when there simply is no other choice).
No, it is not valid to point to an object of Derived with a pointer or reference of Base class. If it were possible, then the whole purpose of private inheritance (hide the fact that the derived class inherits part (or the whole) of its functionality from the base class) would be useless.
Say you have a method foo() in the base class. You don't want this method to be called. But if it were possible to point the object from a pointer of the base class, then it would also be possible to call foo().
Base * ptrBase = &objDerived; // Let's suppose this would compile
ptrBase->foo(); // Now we can call foo() (?)
When you declare private inheritance, is as if the Derived class where not related to the base class. It is just you, the developer, the only one that should "know" that this relationship exist, and actually you should forget about it, because it just won't work.
Private inheritance is just there solely as a reusability mechanism, not as a true inheritance mechanism. It is not recommended to even use it, since you can obtain a better result by simply applying composition (i.e. just make an attribute of class Base in Derived).