Suppose I want to have an inheritance hierarchy like this.
class Base
class DerivedOne : public Base
class DerivedTwo : public Base
The base class is not meant to be instantiated, and thus has some pure virtual functions that the derived classes must define, making it an abstract base class.
However, there are some functions that you would like your derived classes to get from your base class. These functions modify private data members that both DerivedOne and DerivedTwo will have.
class Base {
public:
virtual void MustDefine() =0; // Function that derived classes must define
void UseThis(); // Function that derived classes are meant to use
};
However, the UseThis() function is meant to modify private data members. That's where the question comes in. Should I give the Base class dummy private data members? Should I give it protected data members (and thus the derived classes won't declare their own private data members). I know the second approach will decrease encapsulation.
What is the best approach to a situation like this? If a more detailed explanation is needed I'd be happy to provide it.
If those member variables are supposed to exist in all derived classes then you should declare them in the base class. If you are worried about encapsulation, you can make them private and provide protected accessor methods for derived classes.
Another five cents: the good practice is to have abstract interface class which has no other members, but only public pure virtual methods and often public virtual destructor. Then you create base implementation which can also be abstract but can have protected fields, etc.
In you case it would be something like:
class IBlaBla;
class BlaBlaBase : public IBlaBla;
class DerivedOne : public BlaBlaBase
class DerivedTwo : public BlaBlaBase
This allows you to have more flexibility in the future if you decide that Base is no longer good for some specialized task.
Should I give the Base class dummy
private data members?
If you can implement a part of functionality without exposing the details to the derived classes, then do it in base class. If your derived classes would need access to these members, provide setters and getters. However, it is not convenient to have setters available for derived classes because your code becomes tightly coupled.
Encapsulation is sometimes overrated. If your base class and derived classes need to access those members, then they should probably be protected, not private. If it really is something that needs to be encapsulated, then you may want to make them private but provide getters and setters (either make them private to Base, with getters and setters defined there, or private to the derived classes, with pure virtual getters and setters in Base).
It's a bit hard to give you more specific advice without knowing about the actual problem you're trying to solve.
You will have to define Base::UseThis(), in the body of which you will make use of Base's fields (which you will also need to declare in the class definition above). If you only need to access them in UseThis, they can be private. If DerivedOne/Two will need access to them, you should make them protected.
Here is a possible resolution to your dilemna:
class Base {
public:
virtual ~Base() {}
virtual void redefine_me() = 0;
void utility_function();
private:
virtual int get_data_member() = 0;
virtual void set_data_member(int v) = 0;
};
class Derived1 : public Base {
public:
virtual void redefine_me() { do_d1_stuff(); }
private:
int my_private_idaho_;
virtual int get_data_member() { return my_private_idaho_; }
virtual void set_data_member(int v) { my_rpviate_idaho_ = v; }
};
class Derived2 : public Base {
public:
virtual void redefine_me() { do_d2_stuff(); }
private:
int gomer_pyle_;
virtual int get_data_member() { return gomer_pyle_; }
virtual void set_data_member(int v) { gomer_pyle_ = v; }
};
void Base::utility_function()
{
set_data_member(get_data_member() + 1);
}
It's biggest disadvantage is that now access to the private data member is mediated by a virtual function call, which isn't the cheapest thing around. It's also hidden from the optimizer.
This means that if you choose it, you should adopt a pattern where you fetch the private data member into a local variable at the beginning of your utility function and set it from the local variable before you return. Of course some utility functions may call out to functions that require the object state to be updated before they're called, and this pattern would then have to be modified to account for that. But then again, such utility functions are likely not to be able to satisfy the strong exception handling guarantee and should be rethought anyway.
It looks as if you need some interface for client code, and some 'convenient' functionality for implementors of the interface, which they can only use if they follow the rule of calling the useThis function of the convenience layer, which will tweak their private members.
Whenever I gave in to the temptation of putting the convenience functionality in my abstract base class, I regretted it (soon!) afterwards. It takes away a lot of flexibility. The solution proposed by AlexKR makes this situation slightly better.
An alternative way of doing this is providing some convenience class that implementers of the interface can aggregate instead of inheriting it. It can provide a function taking the implementer's members as arguments.
class Interface { public: virtual void f() = 0; };
class Convenience {
public:
void tweakMyMembers( int& member1, float& member2 );
bool somestate;
};
class Implementor : public Interface {
int m1; float m2;
public: Implementor( bool b ): conv( b ) {}
virtual void f() { conv.tweakMyMembers( m1, m2 ); if( m1<m2 ) dothis(); }
};
Related
The question is that I have multiple specialized base classes to be used by clients to develop the derived classes at clients' end. The multiple specialized base classes are all derived from the same base class. So the derived classes by clients are derived from the same base class, and the same base class pointer can be used to point all client classes. My question is how can I hide the private members and methods of base and specialized base classes from clients, and still allows the client to develop derived classes from the same base class? The very simplified codes are as follows:
In Base.h. This is the single common base of all the following specialized base classes.
class Base {
public:
Base() {}
~Base() {}
void Start();
private:
// methods to override by derived class
virtual void DoExecute() {}
private:
void Execute() {
// Do something here
DoExecute();
// Do something here
}
// Other private methods and members
}
In Base.cpp
void Base::Start() {
Execute();
}
In SpecializedBase1.h. One specialized base class for clients to derived special client class.
class SpecializedBase1 : public Base {
public:
SpecializedBase1();
~SpecializedBase1();
private:
// methods to override by derived class
virtual void DoExecute() {}
// Other private methods and members specialized for this class
}
In SpecializedBase2.h. Another specialized base class for clients to derived special client class.
class SpecializedBase2 : public Base {
public:
SpecializedBase2();
~SpecializedBase2();
private:
// methods to override by derived class
virtual void DoExecute() {}
// Other private methods and members specialized for this class
}
In clients' end, two classes are derived to be called by us.
class ClientClass1 : public SpecializedBase1 {
public:
ClientClass1();
~ClientClass1();
private:
// override base class
void DoExecute() {}
// Other private methods and members specialized for this class
}
class ClientClass2 : public SpecializedBase2 {
public:
ClientClass2();
~ClientClass2();
private:
// override base class
void DoExecute() {}
// Other private methods and members specialized for this class
}
In our end
void Main() {
typedef std::shared_ptr<Base> BasePtr;
std::vector<BasePtr> vec;
// Assume client derived classes creators are available.
vec.push_back(BasePtr(new ClientClass1()));
vec.push_back(BasePtr(new ClientClass2()));
for (auto& step : vec) {
step->Start();
}
}
BTW, this is very simplied verison. Please don't question why we have multiple specialized base classes instead of using the same base class and use pimpl, at this point, it is not possible.
A partial solution: If
you only need hidden private functions (no member variables)
and it is acceptable to make all visible members these functions need to access public
then you could provide these hidden "members" outside the class as non-members, with an explicit pointer to the object. These function can be implemented in the corresponding *.cpp files without being mentioned in the declaration, using static internal linkage or in anonymous namespace, and become completely invisible to clients.
The idea breaks, as soon as you also have private data to hide. The reason is object allocation on the stack. In that case it is the client's responsibility to provide the required memory, which therefore needs to know the object's memory layout including all private members. Impossible, if you hide them. To accomplish this, your would need heap allocation in the constructor, which boils down to PIMPL.
Consider the following base class:
class Base
{
public:
virtual ~Base(void);
virtual void foo(void);
virtual void bar(void) = 0;
}
Now suppose I know that a given class should be the most derived class of Base. Should I declare the functions virtual? The most derived class can/will be used polymorphically with Base.
For example, should I use MostDerived1 or MostDerived2?
class MostDerived1 : public Base
{
public:
~MostDerived1(void);
void foo(void);
void bar(void);
}
class MostDerived2 : public Base
{
public:
virtual ~MostDerived2(void);
virtual void foo(void);
virtual void bar(void);
}
I'm leaning towards MostDerived1 because it most closely models the intent of the programmer: I don't want another child class of MostDerived1 to be used polymorphically with MostDerived1.
Is this reasoning correct? Are there any good reasons why I should pick MostDerived2, aside from the obvious there could be a >0% chance MostDerived2 should be used polymorphically with any deriving classes (class OriginalAssumptionWrong : public MostDerived2)?
Keep in mind MostDerived1/MostDerived2 can both be used polymorphically with Base.
Adding virtual to derived classes doesn't change their behavior, MostDerived and MostDerived2 are have exactly the same behavior.
It does however document your intention, however. I would recommend it for that purpose. The override keyword also helps with this, assuming its available on your platform.
You can't turn off virtualness. Another class derived from either MostDerived1 or MostDerived2 can also override any of the virtual functions regardless of whether you omit the virtual keyword somewhere in the class hierarchy or not.
If you want to enforce that no other class derives from MostDerived1, define it as
class MostDerived1 final : public Base
{
// ...
};
The final keyword can also be used for individual virtual member functions, ensuring no derived class overrides that specific function.
Once function declear somewhere at the hierarchy as a virtual, it's virtual for ever.
You can use final or override if you using C++11
I have a base class with several public methods and want to derive a child class which inherits only certain functions, so I derived the child class using private inheritance. Also I vave come across several times (including C++ primer plus) that private inheritance is almost exactly like containment. Now I have a problem where I want to use a function defined in Base to be available in the derived class.
The derived class doesn't have any private members in addition to those required by the base class. I'm not sure how to define public method "func" for derived class as shown in the code.
class Base
{
private:
double *p;
public:
Base(int m, int n);
void fun(const Base & obj1, const Base & obj2)
};
class Derived : private Base
{
public:
Derived(int n) : Base(1,n) {}
void fun(const Derived & obj1,const Base & obj2)
{
/* The function fun in derived class works almost exactly
like fun in Base class but I don't know how to call
Base.Fun(...). Also all the data needed to perform
operations in this function is a part of the private
member of the base class which the Derived member can't
access.
*/
}
}
If I were to use containment I could have just defined as follows:
class Derived
{
private:
Base P;
public:
void fun(const Derived & obj1,const Base & obj2)
{
Base :: P.func(obj1.P,obj2);
}
};
This make me wonder if containment is more appropriate here than private inheritance. On the other hand I'm not sure if either of the implementations are correct. So I'm looking for possible ways to do this.
Please note that I have not shown copy constructors,assignment and operators and some other methods in the codes above but I'm aware of their requirement. The codes are just to serve the basic purpose of showing private inheritance and containment.
If the fun method of Derived can only be implemented by directly accessing the private members of Base, neither inheritance or containment will allow Derived to access those methods. Using inheritance the member would either need to be protected (or public) or getter/setter methods that are protected (or public) would need to be added. Using composition the public getter/setter methods would be required to avoid making those data members public.
In the fun method of Derived this:
Base::fun(obj1, obj2)
will call the fun method of class Base.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Private virtual method in C++
If I understood correctly from this post (Private virtual method in C++), making a virtual function in a base class makes the derived classes able to override it. But it seems things stop there.
But if the base class virtual function is pure, that forces the derived classes to implement the function. Hence, a pure (public) virtual function is merely an interface. I can see a benefit here.
On the other hand, by making a base class virtual function private, only gives the derived class the ability to override the function, but I see no benefit of this. It's as if that private virtual function is not even there. The derived class obviously does not know about the existence of that virtual function in base class because its private, so is there any benefit of declaring a base class private function virtual, in term of inheritance or polymorphism?
Also, is there any situation where a base class would declare a function 'pure virtual' and 'private'?
Thank you.
One benefit is in implementing the template method pattern:
class Base {
public :
void doSomething() {
doSomething1();
doSomething2();
doSomething3();
}
private:
virtual void doSomething1()=0;
virtual void doSomething2()=0;
virtual void doSomething3()=0;
};
class Derived : public Base {
private:
virtual void doSomething1() { ... }
virtual void doSomething2() { .... }
virtual void doSomething3() { .... }
}
This allows the derived classes to implement each piece of a certain logic, while the base class determines how to put these pieces together. And since the pieces don't make sense by themselves, they are declared private and so hidden from client code.
It is for situations that base wants its children to implement functionality that the base itself needs to use. Imagine a silly example - cars.
class Car {
public:
int getTorque();
int getPower();
private:
virtual const Engine& gimmeEngine() = 0;
};
class Ferrari : public Car {
private:
FerrariEngine myCoolEngine;
const Engine& gimmeEngine() { return myCoolEngine; }
};
Now Car doesn't need to know anything about Ferrari's engine, only that it implements some Engine interface that guaranties that Car can get the information about its power and torque.
In this silly example everything could be simplified by making getTorque and getPower pure virtual, but I hope it illustrates the idea. Base needs to use some specific logic it knows every child must have, so it queries it throught a private pure virtual member.
If the method is virtual it can be overridden by derived classes, even if it's private. Anyway, it should be declared with protected.
I have an abstract class CommandPath, and a number of derived classes as below:
class CommandPath {
public:
virtual CommandResponse handleCommand(std::string) = 0;
virtual CommandResponse execute() = 0;
virtual ~CommandPath() {}
};
class GetTimeCommandPath : public CommandPath {
int stage;
public:
GetTimeCommandPath() : stage(0) {}
CommandResponse handleCommand(std::string);
CommandResponse execute();
};
All of the derived classes have the member variable 'stage'. I want to build a function into all of them which manipulates 'stage' in the same way, so rather than defining it many times I thought I'd build it into the parent class. I moved 'stage' from the private sections of all of the derived classes into the protected section of CommandPath, and added the function as follows:
class CommandPath {
protected:
int stage;
public:
virtual CommandResponse handleCommand(std::string) = 0;
virtual CommandResponse execute() = 0;
std::string confirmCommand(std::string, int, int, std::string, std::string);
virtual ~CommandPath() {}
};
class GetTimeCommandPath : public CommandPath {
public:
GetTimeCommandPath() : stage(0) {}
CommandResponse handleCommand(std::string);
CommandResponse execute();
};
Now my compiler tells me for the constructor lines that none of the derived classes have a member 'stage'. I was under the impression that protected members are visible to derived classes?
The constructor is the same in all classes, so I suppose I could move it to the parent class, but I'm more concerned about finding out why the derived classes aren't able to access the variable.
Also, since previously I've only used the parent class for pure virtual functions, I wanted to confirm that this is the way to go about adding a function to be inherited by all derived classes.
Try this:
class CommandPath {
protected:
int stage;
public:
CommandPath(int stage_) : stage(stage_) {}
};
class GetTimeCommandPath : public CommandPath {
public:
GetTimeCommandPath(int stage_) : CommandPath(stage_) {}
};
(Omitted extra code for brevity).
You can't use the initializer list on a parent class' members, only the current one's. If that makes sense.
First of all: don't use protected for attributes.
It may seem arbitrary, but the point is that it breaks encapsulation. Imagine that suddenly you realize what of space it is to use an int when an unsigned short would have done, so you go ahead and change CommandPath.
Unfortunately, since all the classes deriving from CommandPath could access stage directly, there is a strong change the compiler will complain now: void changeStage(int&); is no longer suitable for example, so you have to reword it... and it's messy.
Proper encapsulation requires that you don't expose your attributes: they are defined as private and you never return handles to them. The idiomatic way is to provide Get and Set methods (you don't necessarily have to change their type, or you may provide overloads, etc...)
Also protected is quite a bastard keyword, it does not protect much and the accessibility restriction it is supposed to define is weak:
class Base { protected: void specialMethod(); };
struct Derived: Base { void specialForward() { specialMethod(); } };
A simple case of deriving and it's now public, that's why it can't be used for encapsulation ;)