Calling virtual methods in C++ is prohibited, however there are a few situations, where it might be very useful.
Consider the following situation - pair of Parent and Child classes. Parent constructor requires a Child class to be instantiated, because it has to initialize it in a special way. Both Parent and Child may be derived, such that DerivedParent uses DerivedChild.
There's a problem, however - because in Parent::ctor call from DerivedParent::ctor, base class should have an instance of DerivedChild instead of Child. But that would require calling a virtual method some way, what is prohibited. I'm talking about something like this:
class Child
{
public:
virtual std::string ToString() { return "Child"; }
};
class DerivedChild : public Child
{
public:
std::string ToString() { return "DerivedChild"; }
};
class Parent
{
protected:
Child * child;
virtual Child * CreateChild() { return new Child(); }
public:
Parent() { child = CreateChild(); }
Child * GetChild() { return child; }
};
class DerivedParent : public Parent
{
protected:
Child * CreateChild() { return new DerivedChild(); }
};
int main(int argc, char * argv[])
{
DerivedParent parent;
printf("%s\n", parent.GetChild()->ToString().c_str());
getchar();
return 0;
}
Let's get a real-world example. Suppose, that I want to write wrapper for WinApi's windows. The base Control class should register class and instantiate a window (eg. RegisterClassEx and CreateWindowEx), to properly set it up (for example register class in such way, that window structure has additional data for class instance; set up generic WndProc for all Controls; put reference to this by SetWindowLongPtr etc.)
On the other hand, derived class should be able to specify styles and extended styles, class name for window etc.
If constructing instance of window in the Control's constructor is a contract to be fulfilled, I see no other solution than to use VMs in ctor (what won't work).
Possible workarounds:
Use static polymorphism (eg. class Derived : public Base), but it will not work, if one wants to derive from Derived;
Pass a lambda from derived to base ctor if it is possible - it will work, but it's a total hardcore solution;
Pass a ton of parameters from derived to base ctor - it shall work, but won't be neither elegant, nor easy to use.
I personally don't like neither of them. Out of curiosity, I checked, how the problem is solved in Delphi's VCL, and you know what, base class calls CreateParams, which is virtual (Delphi allows such calls and guarantees, that they are safe - class fields are initialized to 0 upon creating).
How can one overcome this language restriction?
Edit: In response to answers:
Call CreateChild from the derived constructor. You're already requiring CreateChild to be defined, so this is an incremental step. You can add a protected: void init() function in the base class to keep such initialization encapsulated.
It will work, but it's not an option - quoting the famous C++ FAQ:
The first variation is simplest initially, though the code that actually wants to create objects requires a tiny bit of programmer self-discipline, which in practice means you're doomed. Seriously, if there are only one or two places that actually create objects of this hierarchy, the programmer self-discipline is quite localized and shouldn't cause problems.
Use CRTP. Make the base class a template, have the child supply the DerivedType, and call the constructor that way. This kind of design can sometimes eliminate virtual functions completely.
It's not an option, because it will work only once, for base class and its immediate descendant.
Make the child pointer a constructor argument, for example to a factory function.
This is, so far, the best solution - injecting code into base ctor. In my case, I won't even need to do it, because I can just parametrize base ctor and pass values from the descendant. But it will actually work.
Use a factory function template to generate the child pointer of the appropriate type before returning a parent. This eliminates the complexity of a class template. Use a type traits pattern to group child and parent classes.
Yea, but it has some drawbacks:
Someone, who derives from my classes may publish his ctor and bypass the security measures;
It would prevent one from using references, one would have to use smart pointers.
Calling virtual methods in C++ is prohibited, however there are a few situations, where it might be very useful.
No, calling a virtual method in the constructor dispatches to the most-derived complete object, which is the one under construction. It's not prohibited, it's well-defined and it does the only thing that would make sense.
A C++ base class is not allowed to know the identity of the most derived object, for better or worse. Under the model, the derived object doesn't start to exist until after the base constructors have run, so there's nothing to get type information about.
Some alternatives in your case are:
Call CreateChild from the derived constructor. You're already requiring CreateChild to be defined, so this is an incremental step. You can add a protected: void init() function in the base class to keep such initialization encapsulated.
Use CRTP. Make the base class a template, have the child supply the DerivedType, and call the constructor that way. This kind of design can sometimes eliminate virtual functions completely.
Make the child pointer a constructor argument, for example to a factory function.
Use a factory function template to generate the child pointer of the appropriate type before returning a parent. This eliminates the complexity of a class template. Use a type traits pattern to group child and parent classes.
Related
A situation I often come up against is having a set of classes, Base and Derived, where the Base class has ownership of a base-class member BaseMember, and the Derived class has a reference or pointer to the same object, but as a DerivedMember.
For example, a UI panel class that contains a specific instance of a certain type of control with some special-control functions, inheriting from a general class that contains a general control and has general-control functions.
First, say that BaseMember is inherited by DerivedMemeber.
Without using smart pointers, I might do something like this:
class Base
{
protected:
// receive ownership but only because we say so,
// someone else can still try to delete as it's "just a pointer"
Base(BaseMember* _bmember):
bmember(_bmember)
{}
public:
virtual ~Base()
{
// perform an owner's duty
delete bmember;
}
// functions that might be based on BaseMember + other base state
void SetMemberId(....)
{
bmember->SetId(baz);
}
private:
int baz;
BaseMember* bmember; //owned, but not smartly
}
class Derived: public Base
{
public:
Derived(DerivedMember* _dmember):
Base(_dmember),
dmember(_dmember)
{}
// functions that only make sense for Derived + Derived/Base state
void SetDerivedFrobulation()
{
// only a DerivedMember has frobulation, so only
// Derived allows users to access it
dmember->setFrobulation(foo);
}
private:
int foo; // some state
DerivedMember* dmember; // no ownership here
}
With smart pointers (C++11 and up, specifically, I don't really care about older C++ in this case), I am tempted to do something like this and never let the Base/DerivedMember object out into dumb-pointer-land where it could leak if there was an exception somewhere inconvenient.
class Base
{
protected:
// receive ownership
Base(std::unique_ptr<BaseMember> _member):
member(std::move(_member))
{}
virtual ~Base()
{}
public:
// public access functions here as before
private:
std::unique_ptr<BaseMember> member;
}
class Derived: public Base
{
public:
// pass the ownership down by unique_ptr
Derived(std::unique_ptr<DerivedMember> _dmember):
Base(std::move(_dmember)),
dmember(_dmember.get()) // _dmember is moved! SEGFAULT if access dmember later!
{}
// public access functions here as before
private:
// handy handle to the derived class so we don't need to downcast the base (or even access it!)
DerivedClass* dmember
}
As I noted there, you can't "steal a peek" at the DerivedMember class as it comes in to the Derived constructor, because the unique_ptr is moved away before Derived gets a look in.
I can see a solution in providing a protected access to the BaseMember and static_casting back to DerivedMember in the Derived constructor (i.e. after the Base constructor is done), but this seems an ugly way to get access back to a variable we let slip though our fingers!
Another way could be each inheritor of Base owns the pointer, and base just gets a dumb pointer. In this case, the Base destructor doesn't get access to the member, as it's already gone. Also it would duplicate the ownership logic needlessly.
I think either:
This is symptomatic of an anti-pattern and the design of the whole Base/Derived/BaseMember/DerivedMember system is not good practice.
I'm missing a trick and there is a clean way to do this without fumbling a smart pointer and making a leak possible or adding functions and exposing interfaces or casting too much.
Is this a good pattern for re-use, or should I look elsewhere?
Expanding on the use case (EDIT)
In a core library, I have a class DataInterpreter which shows "some interpretation" of data - could be a string, an image, etc. This is then inherited by, amongst others, TextInterpreter which presents a string.
I then have a DataDisplayPanel class which represents a piece of UI for displaying in an abstract sense. Exactly what is in this panel will depend on the interpreter used: a TextInterpreter should get a text entry field and say a button to set some text display option, and that is handled in TextDisplayPanel, which has "special" knowledge of the text aspect of the interpreter.
There is then a DataAggregatePanel which combines a number of DataDisplayPanels and provides some global settings that affect all displays (via virtual functions), and manages the panels in a std::vector<std::unique_ptr<DataDisplayPanel> >. This aggregate class doesn't deal with any of the derived classes at all, any functions would be polymorphic and defined in the base.
In the application (which depends on the core library), these classes are extended (by inheritance or composition, whichever makes more sense). For example, if the application is a WX GUI, I might have wxDataAggregatePanel which contains wxTextDisplayPanel (and others), all of which are wxPanels. In this case, wxTextDisplayPanel might own a wxTextEntry and either own or inherit TextInterpreter and use its knowledge of the TextInterpreter's specific methods to fill the text box with a string.
You may use delegating constructor:
class Derived: public Base
{
public:
Derived(std::unique_ptr<DerivedMember> _dmember):
Derived(_dmember, _dmember.get())
{}
// public access functions here as before
private:
Derived(std::unique_ptr<DerivedMember>& _dmember, DerivedMember* ptr):
Base(std::move(_dmember)),
dmember(ptr)
{}
private:
// handy handle to the derived class so we don't need to downcast the base (or even access it!)
DerivedClass* dmember
};
I've a question regarding a concept. First, I'm a mechanical engineer and not a programmer, thus I have some C++ knowledge but not much experience. I use the finite element method (FEM) to solve partial differential equations.
I have a base class Solver and two child linSolver, for linear FEM, and nlinSolver for non-linear FEM. The members and methods that both children share are in the base class. The base class members are all protected. Thus using inheritance makes the child classes "easy to use", like there weren't any inheritance or other boundaries. The base class itself, Solver, is incomplete, meaning only the children are of any use to me.
The concept works actually pretty good - but I think that having an unusable class is a bad design. In addition I read that protected inheritance is not preferred and should be avoided if possible. I think the last point don't really apply to my specific use, since I will never use it allow and any attempt to do so will fail (since it is incomplete).
The questions are:
Is it common to use inheritance to reduce double code even if the base class will be unusable?
What are alternatives or better solutions to such a problem?
Is protected inheritance really bad?
Thank you for your time.
Dnaiel
Having "unusable" base classes is actually very common. You can have the base class to define a common interface usable by the classes that inherits the base-class. And if you declare those interface-functions virtual you can use e.g. references or pointers to the base-class and the correct function in the inherited class object will be called.
Like this:
class Base
{
public:
virtual ~Base() {}
virtual void someFunction() = 0; // Declares an abstract function
};
class ChildA : public Base
{
public:
void someFunction() { /* implementation here */ }
};
class ChildB : public Base
{
public:
void someFunction() { /* other implementation here */ }
};
With the above classes, you can do
Base* ptr1 = new ChildA;
Base* ptr2 = new ChildB;
ptr1->someFunction(); // Calls `ChildA::someFunction`
ptr2->someFunction(); // Calls `ChildB::someFunction`
However this will not work:
Base baseObject; // Compilation error! Base class is "unusable" by itself
While the (working) example above is simple, think about what you could do when passing the pointers to a function. Instead of having two overloaded functions each taking the actual class, you can have a single function which takes a pointer to the base class, and the compiler and runtime-system will make sure that the correct (virtual) functions are called:
void aGlobalFunction(Base* ptr)
{
// Will call either `ChildA::someFunction` or `ChildB::someFunction`
// depending on which pointer is passed as argument
ptr->someFunction();
}
...
aGlobalFunction(ptr1);
aGlobalFunction(ptr2);
Even though the base-class is "unusable" directly, it still provides some functionality that is part of the core of how C++ can be (and is) used.
Of course, the base class doesn't have to be all interface, it can contain other common (protected) helper or utility functions that can be used from all classes that inherits the base class. Remember that inheritance is a "is-a" relationship between classes. If you have two different classes that both "is-a" something, then using inheritance is probably a very good solution.
You should check the concept of Abstract class.
It's designed to provide base class that cannot be instantiated.
To do so you provide at least one method in the base class like this
virtual void f()=0;
Each child have to override the f function (or any pure virtual function from the base class) in order to be instantiable.
Don't think of the BaseClass as a class in its own right, but as an interface contract and some implementation help. Therefore, it should be abstract, if neccessary by declaring the dtor pure virtual but providing an implementation anyway. Some OO purists may frown upon any non-private element, but purity is not a good target.
(Note that this is an oversimplification of my actual design.)
Given the following:
class CParentA;
class C_Child
public:
C_Child(C_ParentB* parent) : m_parent(parent){};
virtual ~C_Child();
CParentB* m_parent;
};
class C_ParentA : public C_Child
{
public:
C_ParentA(C_GrandParent *gp) : C_Child(gp){};
virtual ~C_ParentA(){};
}
class C_ParentB
{
public:
C_ParentB(){};
virtual ~C_ParentB(){};
void foo(){};
}
class C_GrandParent : public C_ParentB, public C_ParentA
{
public:
C_GrandParent() : C_ParentA(this){};
virtual ~C_GrandParent();
}
main()
{
C_GrandParent gp;
gp.m_parent->foo();
}
It seems that parentB's pointer, sent to the child's constructor, isn't valid yet when the grandparent is created. I had thought that, even if the parent wasn't fully constructed, it's pointer (this) would still be valid. I've also tried having ParentB be a pointer stored in the grandparent, and the object dynamically created in the grandparent constructor. But that apparently has the same outcome.
FWIW: the goal of this: grandparent has many parents, some of them with children. One child may need access to another child or a parent (uncle/cousin). I had thought that having them all under one patriarch would handle much of the inter-relationships between family members. While that is the case, setting the appropriate pointers seems to be the problem.
First, is is not clear what you are asking, so I am just trying to speculate. You present a design that is not working so you must be asking for alternatives, but you give no information on what you are trying to do.
Second, when class A derives a class B we usually say B is the base or parent and A is the derived or child. You use the opposite terminology and this is very confusing.
Now, I only assume that CParentB* m_parent; in C_Child is supposed to refer to the same C_Child object, viewed as CParentB. You don't need to store a pointer for this. Given a C_Child& r reference or C_Child* p pointer, you can simply say respectively
dynamic_cast<CParentB&>(r)
dynamic_cast<CParentB*>(p)
Both will fail in different ways if r,p do not refer to a CParentB object. dynamic_cast lets you navigate the entire class hierarchy and check at run time if a cast is valid. If the classes are not polymorphic, you can use static_cast instead.
In any case, keep in mind that before any object of a derived class is fully constructed, its bases need to constructed first. So before that, avoid playing in any way with the partially constructed object, like calling its methods especially virtual ones.
I have a base class that clients can "shut down":
struct base {
void shutdown() {
//code
}
};
But clients can (if they want) create a subclass to suit their own needs:
struct der : public base {
void shutdown(double some, int other, bool parameters) {
//custom shutdown stuff
base::shutdown(); //<- thus MUST be called
}
};
The problem is that the client must remember to call base::shutdown() (the superclass creator will document this to subclass developers). This seems error-prone, as nothing is enforced at compile-time.
Are there alternative design patterns to solve this in some way?
Unfortunately, this is one of those cases where you "have to do the right thing" when writing the code. This applies to many things in programming. If you don't do the right calculations when calculating something, that's also wrong. Or if you call a function twice that should only be called once. Or not calling it at all when it has to be called. All of these things are "doing it wrong". You can't prevent programmers from making mistakes...
Of course, if you hadn't added a bunch of extra parameters, you could do it "in reverse" by having a non-virtual function in the base-class that doesn't get overridden, and then let the base-class call a virtual function in the derived class. As I said, it doesn't work if you have parameters that aren't present in the base class that needs to go into the derived class.
An example of what I mean:
struct base {
void shutdown() final { // final: it can't be overridden in derived class
do_shutdown(); // Calls derived function's
// ... more code here ...
}
virtual void do_shutdown() { } // default is "do nothing".
};
struct der: public base
{
// not overriding `shutdown`, but overriding `do_shutdown`
void do_shutdown()
{
.. some code goes here ..
}
}
Now the call to der->shutdown() will call the base-class's implementation, which calls do_shutdown in the derived class before completing the in the base-class's shutdown.
However, like I said, you can't add extra parameters when you do this - in fact, deriving a class and changing the parameters is "wrong" - not so wrong you can't possibly ever do it, but it tends to be a bad thing when using inheritance polymorphism, because the whole purpose of polymorphism is that there is some common code that "doesn't know if it's a base class object, a derived1 object or a derived2 object" - so if it needs to know which kind of object to pass the correct number of arguments, it gets a bit meaningless.
I wouldn't worry about it. It's similar to the assignment operator of derived classes. It's not your fault if the subclass developer forgets to call it, but it's not an error if it isn't either.
C++ FAQ entry on the subject
Building a GUI system and I have a few classes for different GUI components that derive from a base "GUIcontrol" class. What I want is to have just one function to return any type of component but be able to work with the functions specific to that component type (functions of the derived class). I noticed that the polymorphism approach is going to become a problem I have to declare all the derived functions in the base which is unnecessary for this, since I will never create an object just from the base class.
class GUIcontrol {
protected:
std::string _name;
// these two methods (along with name()) will be used by all types
virtual void position(/*parameters*/)
virtual void useImage(/*parameters*/)
// these should be only in derived types
virtual void setHotSpot(/*parameters*/);
virtual void setScrollButtons(/*parameters*/);
public:
std::string name();
/*etc*/
}
class GUIbutton : public GUIcontrol {
public:
void setHotSpot(/*parameters*/);
}
class GUIscrollBar : public GUIcontrol {
public:
void setScrollButtons(/*parameters*/);
}
GUIcontrol* GUIsystem::getControl(std::string name);
The problem with this is that if I want to add more functions unique to GUIbutton or GUIscrollBar, or any functions to other derived GUI classes, I also have to declare them virtual in the base class so the compiler doesn't complain about something like "setHotSpot" not being a member of the base class it returns.
The base class does have member functions that will apply to all the derived classes, such as telling the object where it should be positioned, what image it needs to use, what it should be called, etc. But I don't want to keep stuffing the base class with other functions that need to stay exclusive to certain derived classes.
As I keep adding more virtual functions I would end up with a huge blob object for the base class. Can I design this in a cleaner way? Note that I am still not sure if I want to use static_cast/dynamic_cast for getControl() to solve this but just want to know if there are any other ways around this to clean it up.
The base class should only contain methods for functionality common to all controls.
If you're going to use functionality that only makes sense for one type of control, you should be checking that the control is of the correct type anyway, and can then cast it to that type.
The base class is exclusively common functionality. If you want your method to behave differently for different controls, use dynamic_cast. If you want it to act the same for all controls, use a virtual method.
This is your problem:
What I want is to have just one
function to return any type of
component but be able to work with the
functions specific to that component
type (functions of the derived class).
What you want is to treat them the same but differently. Huh. I wonder how you're going to make that work. You need to decide if you want to treat them all the same, or if you want to treat them differently.
Type checking and then downcasting isn't the right way to do this. What you should be doing is placing generic methods onto your base class which perform the types of operations you want, and then overriding them in subclasses. For example, if you want the GUIControl to be able to draw itself, then put a doDraw() method on the base class, then override that in each subclass to do as is needed. If you instead put a getTitleBar(), getText() etc. methods on your subclass, then have the caller downcast and calls those specific methods depending on the type, your encapsulation is broken. If you have some common code that multiple subclasses need to do their drawing, then you factor this out either through another parent class, or through composition. Using dynamic_cast, or putting specific methods on the generic subclass, will likely make your code worse.
If I have this right: You want to be able to pass around base class objects but have a clean way to call specific derived class methods where the derived class implements those methods?
Sounds like the 'mixin' pattern might help:
struct Base
{
virtual ~Base() {}
};
struct Mixin
{
virtual ~Mixin() {}
virtual void mixedMethod() = 0;
};
struct Concrete : Base, Mixin
{
virtual void mixedMethod() { std::cout << "Mixing" << std:: endl; }
};
Base* create() { return new Concrete;}
bool mixIt(Base& b)
{
Mixin* m = dynamic_cast<Mixin*>(&b);
if (m)
m->mixedMethod();
return m;
}
void test ()
{
Base* b = create();
assert(mixIt(*b));
Base base;
assert(!mixIt(base));
}
[ Yes, real code never uses struct for polymorhic classes; just keeping it compact.]
The idea here is that the availability of a given method is encapsulated in the Mixin class, which is an pure abstract base class, possibly with only a single pure virtual function.
If you want "know" your base class object is of the derived type, you can call the mixin classes method. You can wrap the test and the call in a non-member function; this allows you to keep the base calss interface itself clean.