Let's say we have two classes, Base and Derived. There are two methods, getX and setX, which are public and use a protected int x to interface with the user. Base construction sets x to 1, and Derived construction sets x to 3.
class Base {
public:
Base();
int getX();
void setX(int n);
protected:
int x;
}
int Base::getX() {
return x;
}
void Base::setX(int n) {
x = n;
}
Base::Base() : x(1) {
}
class Derived : public Base {
public:
Derived();
}
Derived::Derived() : x(3) {
}
The Derived class has full access to the methods from Base. Great.
Let's say that for some reason I don't want setX to be available to users of the Derived class. There are a couple ways I thought of doing it.
1) Redeclare setX as private in Derived, so shadowing prevents the user from accessing that method entirely.
2) Redeclare x as a private const int in Derived. However, this results in setX and getX working with Base::x.
3) Make Base::setX a virtual function, make a Derived::setX function that does nothing.
What's the best way to handle this?
As Derived publicly derived from Base, what you are trying to do does not make much sense. You should instead use private or protected inheritance and then provide access in Derived only to methods from Base that you need, not the way around.
First, as observed by anatolyg, shadowing setX method in 1) by making it private in Derived class does not prevent someone to call it on the Base class directly by casting.
So 1) is only ok if you accept this.
Otherwise, if you only want to provide an implementation of setX in Base class to many derived class, but without making it public either to Base or derived class user. just make setX method protected in Base class. In this case you could probably also make x private, and call setX method from Derived constructor.
If you only want to forbid user of any instance of Derived class to call the setX method on that object... but still have it in the interface, well obviously you could as you proposed in 3) make it a virtual function in Base and implement it empty in Derived.
But in this case you are going against the inheritance motto of "is a" (obviously your derived class doesn't behave like the Base class).
If what you are looking is a compilation error to forbid this call,
may be you could rethink your hierarchy:
class real_Base; which does not implements setX method
class Base : public real_Base; which implements setX method
class Derived : public real_Base; which does not implement setX method
In this case then:
you would use real_Base as interface when your client code does not need to call setX.
use Base when call to setX is allowed
use Derived when call to setX is forbidden.
You aren't overriding any virtual functions so inheritance is dubious.
Do you want users to use the Base interface or the Derived interface? If you say Derived, again that's dubious.
Compose Derived from Base and give it a better name:
class Composite {
private:
Base base;
public:
Composite() : base(3) {
}
};
You cannot initialize member x in the initializer list of Derived, since x is not a member of Derived. Your compiler should issue an error.
Related
I have a similar situation to this question where I have 2 classes that share a public interface function, and so I've pulled that function (manage_data_in_memory() in the example) out into a base class which the 2 classes inherit from. However, the 2 classes are otherwise not related, and one of them is polymorphic, whereas the other one isn't. It is also not expected for someone to declare an object of this base class, as it exists only to prevent code duplication (is there a way to enforce this? I know pure virtual functions can prevent an object from being instantiated, but declaring a dummy pure virtual that does nothing in the derived class seems like bad design).
Does the base class destructor need to be virtual in this case? This would force the other derived class to also have a virtual destructor, which it doesn't need.
Thanks.
So now I have code in the form
class base { // don't instantiate an object of this, is there a way to enforce this?
public:
void manage_data_in_memory();
protected:
data;
};
class derived : public base
{
public:
void sendData();
private:
virtual void sendDataHelper(); // override this in derived classes which need to send custom data in addition to the default data
};
class derived2 : public base
{
public:
void do_Z_On_data()
};
The destructor of a base class must be virtual if and only if an instance of a derived class will be destroyed through a pointer to the base object. If the destructor isn't virtual in such case, then the behaviour of the program would be undefined. Example:
struct Base {
// ...
};
struct Derived : Base {};
std::unique_ptr<Base> ptr = std::make_unique<Derived>();
// Base::~Base must be virtual
It's possible to prevent the user of the class from doing this (at least by accident) by using private inheritance. If the destructor isn't virtual, then inheritance should be private except possibly in special cases where you need a standard layout class.
is this because private inheritance would make the destructor private
No, private inheritance doesn't make destructor private.
which prevents anyone from declaring an object of Base?
No, and declaring an object of Base isn't a problem.
Private inheritance prevents conversion from derived pointer into a base pointer outside the member functions of the derived class (and friends). The inability acquire a pointer to base of the derived class would prevent the user from deleting a derived object through such pointer.
I'd like to add the extra functionality without changing the existing class.
Say,
class base{
public:
int i;
base(){i = 1;}
virtual void do_work(){ /*Do some work*/ }
};
If I want to add serialization member function to it, I will simply create a derived class
class derived : public base{
public:
void serialize();
};
void derived::serialize(){
cout << "derived class" << endl;
}
And I do need to handle existing base objects,e.g.
int main(){
base a;
derived & b = static_cast<derived &>(a);
b.serialize();
}
This example runs without problems. But I do know the downcast through static_cast is something to be avoided in general.
But I'd like to know if the downcast for this particular use case can be considered safe since the derived class only has one extra member function. Will it has some potential undefined behavior for accessing vtable?
The way you're extending Base you're not making use of the vtable because you have no virtual methods. It may be easier to think of it as Derived has A Base; That you created a new class that contains a Base member variable.
My Suggestion.
Template Function
I personally would go with a template function. You can keep all the work in your original question, and avoid the need of adding virtual calls to your class.
template<typename T>
void serialize_object(T& t)
{
t.serialize()
}
And then based on your example.
Derivied d;
serialize_object(d);
The big benefit is that you're not adding runtime cast here. The compiler will inform you if you pass an object that doesn't have a method serialize.
Go Virtual
If you really want to handle this through a virtual interface do so.
struct Serializable{
virtual void serialize()=0;
virtual ~Serializable(){}
}
class Derived : public Serializable {
public:
void serialize() override;
}
void Derivied::serialize()
{
std::cout << "Yah\n";
}
Then in your code.
Derivied d;
Serializable& s = dynamic_cast<Serializable&>(d);
However, the big concern here is who is the owner of your base class? Did they provide a virtual dtor? If not, then making use of std::unique_ptr or std::shared_ptr could cause you to not deal directly with the interface.
If you can write the serialize function in a derived class without touching private or protected members then you should simply make it a free function. That solves everything.
You can't just cast a base class object to an inherited class. Any members in the inherited class will not have been created and initialized. You need to start with an object of the inherited class.
You can go the other way, of course, and call base class functions from a function of a class inherited from the base, because the base class object will always be there as part of the inherited class object, by definition.
If you have a pointer to the base class, and you build with RTTI, you can use dynamic_cast to cast to an inherited class, but that cast will fail and return NULL if the object is not of the class you're trying to cast to. But usually it's better to call a virtual function than to use dynamic_cast.
Suppose I have a Base class and its derived class Derived as follows:
class Base{
private:
_privateVar;
protected:
protectedVar;
public:
publicVar;
void publicMethod(someValue, anotherValue)
{
protectedVar = someValue;
publicVar = anotherValue;
}
};
class Dervied: public Base{
protected:
protectedVar:
};
int main(void)
{
Dervied d;
d.publicMethod(valueA, valueB);
}
My question-
When I call d.publicMethod(...), does the protectedVar in Derived get set or the one in Base class?
Thanks
--A
It is of Base class. Base class cannot access derived class members.
When I call d.publicMethod(...), does the protectedVar in Derived get set or the one in Base class?
The method is a member of the Base class and hence it can access only the members of the Base class.
If the method belonged to your Derived class, then it would access Derived class member.
Because Derived class data members always hide Base class data members when accessed inside their own member functions.
You cannot override a member variable, you can create another different variable in a different level in the hierarchy that has the same name, but they will be two unrelated variables. Within the context of the use of the variable, lookup will find one or the other and that is the one that will be picked up and used.
Polymorphism only applies to virtual member functions, not to non-virtual functions, not to member variables either.
Since publicMethod is a methoc of the Base class, the protectedVar of the base class is set.
I don't know if this is what you want or expect, but even if this is what you want, I think it is not advised to do it like this. Tools like PC-LINT will probably also warn you about such a construction.
The member in the base class is modified. Data members never behave as if they are virtual.
When the compiler reaches the definition of Base::publicMethod, it has to statically resolve all the names it uses. At that point, the only possible resolution of those names are the members of Base, so the generated code will access those members.
Subclassing Base later on does not, and could not possibly, go back and change the code generated for Base::publicMethod. The derived class could be in a different translation unit, or in a dynamically-loaded library.
If you want dynamic lookup, access protectedVar via a protected virtual accessor function: that would allow a derived class to interpose its own storage for the variable.
If Base::protectedVar and Derived::protectedVar have the same type anyway, it's hard to see what you expect to gain, but it would look like:
class Base
{
Type protectedVarImpl;
protected:
virtual Type & protectedVar();
virtual Type const & protectedVar() const;
public:
void publicMethod(someValue, anotherValue)
{
protectedVar() = someValue; // Note the method call
publicVar = anotherValue;
}
};
Type& Base::protectedVar() { return protectedVarImpl; }
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).
I have seen this question http://www.careercup.com/question?id=384062
class Base {
public :
virtual void method () = 0;
private :
int n;
};
void Base::method() { n = 1;}
class D1 : Base {};
class D2 : public D1 {
int i;
void method() {i = 2;}
};
It passed the compiler of vs2008 and g++ 4.4.3
Here is my understanding of above code, please correct me if I am wrong
S1> D1 has inherited variable Base::n but it cannot access it.
S2> D1 has inherited the function Base::method but it doesn't call/modify this inherited function in the above implementation.
S3> D2::method is not an overridden version of D1::method
S2 and S3 are wrong.
D1's methods can call it's Base::method(), but other code can't as Base part of D1 is private.
Base::method() is overridden by D2. If you somehow convert (new D2) to (Base*) and call Base::method, the i=2 code will run.
Considering access control, if you have pointer to Base*, external code can use ->method() because it's public, and if you have pointer to D2*, ->method() can't be called because it's private, even if it's the same object and the same method.
Also, despite your (n=1) implementation for Base::method() it and its class remain abstract.
D1 has inherited variable Base::n but it cannot access it.
Correct.
Private members of a class are never accessible from anywhere except the members of the same class.
D1 has inherited the function Base::method but it doesn't call/modify this inherited function in the above implementation.
Correct, but conditonally, Read below for why:
D1 inherits the Base::method but it is not calling/invoking it because you did'nt add any statement to do so. But it can call it.
Pure virtual functions can have a body and they can be called by drived class members just like any other member function.
class D1 : Base
{
public:
void doSomething()
{
Base::method();
}
};
Note that in your Base class n is private so the only way to access it is through member function of Base & since only method() can do so, You can do it through it.
Note that presence of atleast one pure virtual function makes an class Abstract Class, And one cannot create objects of an Abstract class. Any class deriving from an Abstract class must override ALL the pure virtual functions of the Base class or else the derived class becomes an Abstract class as well.
Based on above rule,
In your case both Base and D1 are Abstract classes.
D2::method is not an overridden version of D1::method
Incorrect
Though method() is not acessible to the ouside world through instance of class D1, it is still very much a part of it. Access control dictates access rights not presence or absence of members.
So, Yes, D2::method is an overriden version of D1::method and it hides it as well, just that in this case, D1::method was not acccessible in the first place
In this case both Base and D1 classes are abstract classes which cannot be instantiated.
S1 - yes
S2 - Yes D1 has inherited the function. Can you please clarify your question.
S3 - No. D2::method is the override you have provided for the D2 class.
Edit:
I just noticed the private inheritance of D1 from Base class. In that case, S1 and S2 still hold good.
Updated: S3: D2::method is both overriding and hiding the base class method.
S1: Correct
S2: Correct
S3: Correct, more clearly D2::method hides D1::method
S1 - Correct
S2 - Sorry I'm not very clear what you meant. In D1 or subclasses you can define method() to override it in Base but cannot call it. And, D1* cannot be converted to Base* because of private inheritance.
S3 - Incorrect. Once you declare a member function as virtual in the base class, it will keep virtual in subclasses even you leave out virtual. So in your case, method() in D2 is a overridden version of D1::method() and Base::method().