dynamic_cast vs virtual AsDerived method in base - c++

When trying to access derived class behaviour, the most common approach I read about is using dynamic_casts, i.e. dynamic_cast<DerivedA*>(BasePtr)->DerivedAOnlyMethod(). This isn't really pretty, but everybody understands what's going on.
Now I'm working on a code where this conversion is handled by virtual functions exported to the base class, for each derived class, i.e.:
class Base
{
public:
virtual DerivedA* AsDerivedA() { throw Exception("Not an A"); }
virtual DerivedB* AsDerivedB() { throw Exception("Not a B"); }
// etc.
};
class DerivedA : public Base
{
public:
DerivedA* AsDerivedA() { return this; }
};
// etc.
Use is then BasePtr->AsDerivedA()->DerivedAOnlyMethod(). Imho, this clutters up the base class, and exposes knowledge about the derived classes it shouldn't need.
I'm too inexperienced to say with certainty which is better, so I'm looking for arguments for and against either construct. Which is more idiomatic? How do they compare regarding performance and safety?

Well, putting the AsDerived#-methods into the base-class certainly leads to potentially faster casting.
If you cap the inheritance-hierarchy using final that advantage might be reduced or removed though.
Also, you are right about it being uncommon because it introduces clutter, and it introduces knowledge of all relevant derived classes into the base-class.
In summary, it might sometimes be useful in a bottleneck, but you will pay for that abomination.

Without seeing more code it is difficult to offer too much advice. However, needing to know the type of the object you're calling into argues more for a variant than a polymorphic type.
polymorphism is about information hiding. The caller should not need to know what type he is holding.
something like this, perhaps?
struct base
{
virtual bool can_do_x() const { return false; }
virtual void do_x() { throw std::runtime_error("can't"); }
virtual ~base() = default;
};
struct derived_a : base
{
virtual bool can_do_x() const { return true; }
virtual void do_x() { std::cout << "no problem!"; }
};
int main()
{
std::unique_ptr<base> p = std::make_unique<derived_a>();
if (p->can_do_x()) {
p->do_x();
}
}
Now we're talking to the object in terms of capabilities, not types.

Your intuition is right, the AsDerivedX methods are clutter. The fact that at runtime it can be checked whether these virtual functions were overloaded is equivalent to the cost of a typecheck. So, in my opinion, the C++ way of doing this is:
void doSomething(Base *unsureWhichAorB) {
DerivedA *dA = dynamic_cast<DerivedA*>(unsureWhichAorB);
if(dA) //if the dynamic cast failed, then dA would be 0
dA->DerivedAOnlyMethod();
}
Note that the check for non-zeroness of dA is critical here.

You are totally correct that such a solution not only clutters the base class but also puts unnecessary dependencies on it. In a clean design the base class does not need to and actually should not know anything about its derived classes. Everything else will become a maintenance nightmare pretty soon.
However, I'd like to point out that I am in the "try to avoid dynamic_cast"-Team. Meaning that I often see dynamic_cast that could have been avoided with a proper design. So the question to ask in the first place would be: Why do I need to know the derived type? Usually there is either a way to solve the problem by using polymorphism correctly or "losing" the type information already was the wrong path.
Prefer to use polymorphism instead of dynamic_cast:
class Base
{
public:
virtual void doSomething() = 0;
};
class DerivedA : public Base
{
public:
void doSomething() override { //do something the DerivedA-way };
};
class DerivedB : public Base
{
public:
void doSomething() override { //do something the DerivedB-way };
};
// etc.

Related

avoid vtable mixup in c++ variadic template inheritance

I have an idea to architecting classical entity-component in a better way with variadic template inheritance. This question stems from funky experiments in the context of 3d-graphics but i believe i have it broken down to a very abstract question about C++. I am able to use C++20 in the scope in which it is currently implemented in Microsoft cl aka. the MSVC++19-Toolchain.
So. A few Base classes:
class basic {
public:
std::wstring get_name() { return name; }
virtual void do_something_idk_virtual() = 0;
virtual ~basic() {}
private:
std::wstring name;
}
class has_legs {
public:
virtual void walk() = 0;
virtual ~has_legs() {}
}
class has_wings {
public:
virtual void fly() = 0;
virtual ~has_wings() {}
}
template<typename... Ts>
class entity : public basic, public Ts... {
public:
virtual ~entity() {}
}
So far, so good. Now i want to make a duck:
class duck : entity<has_wings, has_legs> {
public:
virtual ~duck() {}
virtual void walk() { cout << "walk" << endl; }
virtual void fly() { cout << "fly" << endl; }
virtual void do_something_idk_virtual() { } // nothing,
}
still, seems to work. The problem is: I know have data structure (say a linked_list, or some sort of graph) and I use the visitor-pattern to work with basic*-typed things. I now have a lot of Code that looks like this. This is, quite literally, the central and critical part of a my program:
void visit(basic* node) {
//here i find out, through magic or some other kind of out-of-scope-mechanism that node is at least a has_wings. Problem:
reinterpret_cast<has_wings*>(node)->fly(); //does not work, will call basic::do_something_idk_virtual(). As far as i understand, this is because the compiler-generated vtable does not change via the reinterpret_cast.
reinterpret_cast<entity<has_wings>*>(node)->fly(); //might, work, problems start to come in if node is of some type that has_wings and has_legs. It sometimes calls some other method, depending on the ordering in declaring the class.
}
Solution
Have every component (aka. the pure interfaces) and the entity-class virtually inherit from basic
in basic add the non-virtual method:
template<typename TComponent> TComponent* get_component() {
return dynamic_cast<TComponent*>(this);
}
This will then fix vtables. I am not sure why dynamic_cast does that.
First of all, your template gives you nothing. class duck : public basic, public has_wings, public has_legs is absolutely identical.
Second, you need to decide what your level of polymorphic access is. If your level is basic, than it has to have already defined all the virtuals you want to be accessing (i.e. has_wings, fly) An interface where you need dynamic_casts to arrive to correct dynamic type (your example with reinterpret_cast is just wrong, you can't use reinterpret_cast to move through class hierarchy) is a poorly written interface.
Sometimes visitor pattern can be employed, but in my mind, it tends to produce extremely hard to troubleshoot code.
You have to use static_cast or dynamic_cast to move within an inheritance hierarchy, and static_cast can’t descend virtual inheritance or cross-cast (in one step) because the layout of different classes that derive from the source and destination types may differ. As it is, you’d have to know the actual type (not just that it had a given aspect) to do the conversion. If you have your “aspect” classes inherit from basic—virtually, so that there is a unique basic* to be had—you can then use dynamic_cast not for its checking purpose but so as to find the appropriate vtable for the aspect in question.
If you can’t afford that, you may want to amalgamate the interfaces somehow. You then have to be careful to call the functions only when they’re meaningful; that’s already the case (“through magic”), but then the ordinary call syntax might be an attractive nuisance. You might also try some C-style polymorphism with a manually-created vtable with function pointers for each optional behavior.

Call an interface function from an unknown derived class (multiple inheritance)

I have an array of Base* objects. This holds a bunch of derived objects, some of which may implement an Interface.
struct Base {
virtual void doNotCallThis() { cout << "nooo" << endl; }
};
struct Interface {
virtual void doThis() = 0;
};
// Example derived class
struct Derived : Base, virtual Interface {
virtual void doThis() { cout << "yes" << endl; }
};
int main() {
Base* b[1];
b[0] = new Derived(); // Here would be a bunch of different derived classes
((Interface*)b[0])->doThis(); // Elsewhere, doThis() would be called for select array elements
return 0;
}
Output:
nooo
I don't know the exact type of b[i] at run time, so I can't cast to Derived (it could be Derived2, Derived3, etc). I also can't use dynamic_cast if that's a solution. All I know is that, by the time I call doThis(), b[i] is a type that inherits from Interface. The way I attempted to call it above causes the wrong function to be called, eg. Base::doNotCallThis().
How can I call it properly?
As other people have pointed out, you would probably do best to find a way to refactor your design so that casting isn't necessary.
But putting that aside, I can explain what's going wrong and how to correctly cast.
The problem with ((Interface*)b[0]) is that since Base and Interface are unrelated the compiler has to do a blind reinterpretive cast. Practically speaking that means in this situation the resulting pointer doesn't actually line up with the Interface part of the object. If you were to try static_cast<Interface*>(b[0]) you would find it doesn't compile - and that's a big hint that it's the wrong kind of cast to be making.
On the other hand, the compiler does know the relationship from Base to Derived and also from Derived to Interface. So as long as you know for sure that the object not only implements Interface but also is a Derived then you can do:
static_cast<Interface*>(static_cast<Derived*>(b[0]))->doThis();
However if your design has multiple different derived types which independently implement Interface then you might not be able to do that unless again you absolutely know what the derived type is at any time you go to make the call. - This is why refactoring it into a better class hierarchy is more desirable, since it's much less fragile and cumbersome to work with.
(As a side note, this issue points out why it's a great idea to never use raw/reintrepretive casts when moving up and down a class hierarchy. At least use static_cast since the can compiler better help you do it correctly.)
Writing an answer with the risk of being downvoted:
If we start with::
struct Base()
{
virtual void SomeFunc();
};
struct Interface
{
virtual void doThis();
}
then to create a bunch of derived functions from Base that are also interfaces, I'd do something like this:
struct BaseInterface : public Base, public Interface
{
// Nothing here - this is just combining Base and Interface
};
struct Base1 : public BaseInterface
{
... add stuff that Base1 has that isn't in Base.
};
struct Derived: public Base1
{
... some more stuff that isn't in Base1
}
And then we use it in Main like this:
int main() {
BaseInterface* b[1];
b[0] = new Derived(); // Here would be a bunch of different derived classes
b[0])->doThis(); // Elsewhere, doThis() would be called for select array elements
return 0;
}

Can you prevent inherited private members being called through the parent at compile time?

If you have a feature rich class, possibly one you do not own/control, it is often the case where you want to add some functionality so deriving makes sense.
Occasionally you want to subtract as well, that is disallow some part of the base interface. The common idiom I have seen is to derive and make some member functions private and then not implement them. As follows:
class Base
{
public:
virtual void foo() {}
void goo() { this->foo(); }
};
class Derived : public Base
{
private:
void foo();
};
someplace else:
Base * b= new Derived;
and yet another place:
b->foo(); // Any way to prevent this at compile time?
b->goo(); // or this?
It seems that if the compilation doesn't know that it is derived, the best you can do is not implement and have it fail at runtime.
The issue arises when you have a library, that you can't change, that takes a pointer to base, and you can implement some of the methods, but not all. So part of the library is useful, but you run the risk of core dumping if you don't know at compile time which functions will call what.
To make it more difficult, others may inherit from you class and want to use the library, and they may add some of the functions you didn't.
Is there another way? in C++11? in C++14?
Let's analyze this, focused on two major points:
class Base
{
public:
virtual void foo() {} // This 1)
// ...
class Derived : public Base // and this 2)
In 1) you tell the world that every object of Base offers the method foo() publicly. This implies that when I have Base*b I can call b->foo() - and b->goo().
In 2) you tell the world that your class Derived publicly behaves like a Base. Thus the following is possible:
void call(Base *b) { b->foo(); }
int main() {
Derived *b = new Derived();
call(b);
delete b;
}
Hopefully you see that there is no way call(Base*) can know if b is a derived and thus it can't possibly decide at compile-time if calling foo wouldn't be legal.
There are two ways to handle this:
You could change the visibility of foo(). This is probably not what you want because other classes can derive from Base and someone wants to call foo afterall. Keep in mind that virtual methods can be private, so you should probably declare Base as
class Base
{
virtual void foo() {}
public:
void goo() { this->foo(); }
};
You can change Derived so that it inherits either protected or private from Base. This implies that nobody/only inheriting classes can "see" that Derived is a Base and a call to foo()/goo() is not allowed:
class Derived : private Base
{
private:
void foo() override;
// Friends of this class can see the Base aspect
// .... OR
// public: // this way
// void foo(); // would allow access to foo()
};
// Derived d; d.goo() // <-- illegal
// d.foo() // <-- illegal because `private Base` is invisible
You should generally go with the latter because it doesn't involve changing the interface of the Base class - the "real" utility.
TL;DR: Deriving a class is a contract to provide at least that interface. Subtraction is not possible.
This seems to be what you want to do:
struct Library {
int balance();
virtual int giveth(); // overrideable
int taketh(); // part of the library
};
/* compiled into the library's object code: */
int Library::balance() { return giveth() - taketh(); }
/* Back in header files */
// PSEUDO CODE
struct IHaveABadFeelingAboutThis : public Library {
int giveth() override; // my implementation of this
int taketh() = delete; // NO TAKE!
};
So that you can't call taketh() on an IHaveABadFeelingAboutThis even when it is cast as the base class.
int main() {
IHaveABadFeelingAboutThis x;
Library* lib = &x;
lib->taketh(); // Compile error: NO TAKE CANDLE!
// but how should this be handled?
lib->balance();
}
If you want to present a different interface than the underlying library you need a facade to present your interface instead of the that of the library.
class Facade {
struct LibraryImpl : public Library {
int giveth() override;
};
LibraryImpl m_impl;
public:
int balance() { return m_impl.balance(); }
virtual int giveth() { return m_impl.giveth(); }
// don't declare taketh
};
int main() {
Facade f;
int g = f.giveth();
int t = f.taketh(); // compile error: undefined
}
Although I don't think your overall situation is good design, and I share many of the sentiments in the comments, I can also appreciate that a lot of code you don't control is involved. I don't believe there is any compile time solution to your problem that has well defined behavior, but what is far preferable to making methods private and not implementing them is to implement the entire interface and simply make any methods you can't cope with throw an exception. This way at least the behavior is defined, and you can even do try/catch if you think you can recover from a library function needing interface you can't provide. Making the best of a bad situation, I think.
If you have class A:public B, then you should follow the https://en.wikipedia.org/wiki/Liskov_substitution_principle
The Liskov substitution principle is that a pointer-to-A can be used as a pointer-to-B in all circumstances. Any requirements that B has, A should satisfy.
This is tricky to pull off, and is one of the reasons why many consider OO-style inheritance far less useful than it looks.
Your base exposes a virtual void foo(). The usual contract means that such a foo can be called, and if its preconditions are met, it will return.
If you derive from base, you cannot strengthen the preconditions, nor relax the postconditions.
On the other hand, if base::foo() was documented (and consumers of base supported) the possibility of it throwing an error (say, method_does_not_exist), then you could derive, and have your implementation throw that error. Note that even if the contract says it could do this, in practice if this isn't tested consumers may not work.
Violating the Liskov substitution principle is a great way to have lots of bugs and unmaintainable code. Only do it if you really, really need to.

c++ factory and casting issue

I have a project where I have a lot of related Info classes and I was considering putting up a hierarchy by having a AbstractInfo class and then a bunch of derived classes, overriding the implementations of AbstractInfo as necessary. However it turns out that in C++ using the AbstractInfo class to then create one of the derived objects is not that simple. (see this question, comment on last answer)
I was going to create like a factory class which creates an Info object and always returns an AbstractInfo object. I know from C# you can do that with interfaces, but in C++ things are a little different it seems.
Down casting becomes a complicated affair and it seems prone to error.
Does anyone have a better suggestion for my problem?
You don't require downcasting. See this example:
class AbstractInfo
{
public:
virtual ~AbstractInfo() {}
virtual void f() = 0;
};
class ConcreteInfo1 : public AbstractInfo
{
public:
void f()
{
cout<<"Info1::f()\n";
}
};
class ConcreteInfo2 : public AbstractInfo
{
public:
void f()
{
cout<<"Info2::f()\n";
}
};
AbstractInfo* createInfo(int id)
{
AbstractInfo* pInfo = NULL;
switch(id)
{
case 1:
pInfo = new ConcreteInfo1;
break;
case 2:
default:
pInfo = new ConcreteInfo2;
}
return pInfo;
}
int main()
{
AbstractInfo* pInfo = createInfo(1);
pInfo->f();
return 0;
}
Don't downcast - use virtual methods. Just return the pointer to a base class from the factory and only work through that pointer.
class AbstractInfo
{
public:
virtual ~AbstractInfo();
virtual X f();
...
};
class Info_1 : public AbstractInfo
{
...
};
class Info_2 : public AbstractInfo
{
...
};
AbstractInfo* factory(inputs...)
{
if (conditions where you would want an Info_1)
return new Info_1(...);
else if (condtions for an Info_2)
return new Info_2(...);
else
moan_loudly();
}
If you don't want the factory method to become a single point of maintenance as downstream client code adds Info types, you can instead provide some mechanism for client code to register methods for creation of those derived objects. Check out the Gang of Four's Design Patterns book for creational patterns, or google them.
While generally you can't overload on return types in C++, there is an exception for covariant return types
Example taken from wikipedia:
// Classes used as return types:
class A {
}
class B : public A {
}
// Classes demonstrating method overriding:
class C {
A* getFoo() {
return new A();
}
}
class D : public C {
B* getFoo() {
return new B();
}
}
Thus eliminating the need for casting.
C++ provides polymorphism just as C# does. The language has no special interface-type, but you can emulate that by using a class that only has pure virtual methods. In C# all methods are virtual by default (meaning they are bound at runtime), whereas in C++ you have to declare that explicitly using the virtual-keyword. Also, C# handles all objects using references (as far as I know), whereas in C++ you have to choose between values, pointers or references. In your case, you most likely want your factory to return a pointer to the interface, or even better a smart pointer, so you don't have to worry about memory management.
To elaborate / pontificate a little, the "good" time to use an abstract interface (eg: base class with virtual functions) is when substantially all the functionality which will be used on the objects can be contained in virtual functions. If that's the case, you can do what you're proposing easily, and just call the virtual functions on the base class pointer, which will automatically call the most-derived version provided.
If you find yourself needing to downcast often to get at child-class specific functions/data, this approach is probably not optimal for your situation. In that case you may find yourself writing some of the functionality outside the classes, providing multiple implementations for each type, and using some sort of RTTI to help downcast as necessary. This is more messy, but tends to be more common outside of the "academic" or well-isolated usages.
Looks like you've got a lot of good info/advice here in the other answers, though.

Inheritence and usage of dynamic_cast

Suppose I have 3 classes as follows (as this is an example, it will not compile!):
class Base
{
public:
Base(){}
virtual ~Base(){}
virtual void DoSomething() = 0;
virtual void DoSomethingElse() = 0;
};
class Derived1
{
public:
Derived1(){}
virtual ~Derived1(){}
virtual void DoSomething(){ ... }
virtual void DoSomethingElse(){ ... }
virtual void SpecialD1DoSomething{ ... }
};
class Derived2
{
public:
Derived2(){}
virtual ~Derived2(){}
virtual void DoSomething(){ ... }
virtual void DoSomethingElse(){ ... }
virtual void SpecialD2DoSomething{ ... }
};
I want to create an instance of Derived1 or Derived2 depending on some setting that is not available until run-time.
As I cannot determine the derived type until run-time, then do you think the following is bad practice?...
class X
{
public:
....
void GetConfigurationValue()
{
....
// Get configuration setting, I need a "Derived1"
b = new Derived1();
// Now I want to call the special DoSomething for Derived1
(dynamic_cast<Derived1*>(b))->SpecialD1DoSomething();
}
private:
Base* b;
};
I have generally read that usage of dynamic_cast is bad, but as I said, I don't know
which type to create until run-time. Please help!
Why not delay the moment at which you "throw away" some if the type information by assigning a pointer to derived to a pointer to base:
void GetConfigurationValue()
{
// ...
// Get configuration setting, I need a "Derived1"
Derived1* d1 = new Derived1();
b = d1;
// Now I want to call the special DoSomething for Derived1
d1->SpecialD1DoSomething();
}
The point of virtual functions is that once you have the right kind of object, you can call the right function without knowing which derived class this object is -- you just call the virtual function, and it does the right thing.
You only need a dynamic_cast when you have a derived class that defines something different that's not present in the base class, and you need/want to take the extra something into account.
For example:
struct Base {
virtual void do_something() {}
};
struct Derived : Base {
virtual void do_something() {} // override dosomething
virtual void do_something_else() {} // add a new function
};
Now, if you just want to call do_something(), a dynamic_cast is completely unnecessary. For example, you can have a collection of Base *, and just invoke do_something() on every one, without paying any attention to whether the object is really a Base or a Derived.
When/if you have a Base *, and you want to invoke do_something_else(), then you can use a dynamic_cast to figure out whether the object itself is really a Derived so you can invoke that.
Using dynamic_cast is not bad practice per se. It's bad practice to use it inappropriately, i.e. where it's not really needed.
It's also a bad practice to use it this way:
(dynamic_cast<Derived1*>(b))->SpecialD1DoSomething();
Reason: dynamic_cast(b) may return NULL.
When using dynamic_cast, you have to be extra careful, because it's not guaranteed, that b is actually of type Derived1 and not Derived2:
void GenericFunction(Base* p)
{
(dynamic_cast<Derived1*>(b))->SpecialD1DoSomething();
}
void InitiallyImplementedFunction()
{
Derived1 d1;
GenericFunction(&d1); // OK... But not for long.
// Especially, if implementation of GenericFunction is in another library
// with not source code available to even see its implementation
// -- just headers
}
void SomeOtherFunctionProbablyInAnotherUnitOfCompilation()
{
Derived2 d2;
GenericFunction(&d2); // oops!
}
You have to check if dynamic_cast is actually successful. There are two ways of doing it: checking it before and after the cast. Before the cast you can check if the pointer you're trying to cast is actually the one you expect via RTTI:
if (typeid(b) == typeid(Derived1*))
{
// in this case it's safe to call the function right
// away without additional checks
dynamic_cast<Derived1*>(b)->SpecialD1DoSomething();
}
else
{
// do something else, like try to cast to Derived2 and then call
// Derived2::SpecialD2DoSomething() in a similar fashion
}
Checking it post-factum is actually a bit simpler:
Derived1* d1 = dynamic_cast<Derived1*>(b);
if (d1 != NULL)
{
d1->SpecialD1DoSomething();
}
I'd also say it's a bad practice to try and save typing while programming in C++. There are many features in C++ than seem to be completely fine to be typed shorter (i.e. makes you feel 'that NULL will never happen here'), but turn out to be a pain in the ass to debug afterwards. ;)
Some other things you might like to consider to avoid the use of dynamic_cast
From Effective C++ (Third Edition) - Item 35 Alternatives to virtual functions -
'Template Method pattern' via Non-Vitual Interface (NVI). Making the virtual functions private/protected with a public method 'wrapper' - allows you to enforce some other workflow of stuff to do before and after the virtual method.
'Strategy pattern' via function pointers. Pass in the extra method as a function pointer.
'Strategy pattern' via tr1::function. similar to 2. but you could provide whole classes with various options
'Strategy pattern' classic. Seperate Strategy from main class - push the virtual functions into another hierarchy.
There is a pattern named Factory Pattern that would fit this scenario. This allows you to return an instance of the correct class based on some input parameter.
Enjoy!
What is wrong with:
Base * b;
if( some_condition ) {
b = new Derived1;
}
else {
b = new Derived2;
}
if ( Derived2 * d2 = dynamic_cast <Derived2 *>( b ) ) {
d2->SpecialD2DoSomething();
}
Or am I missing something?
And can OI suggest that when posting questions like this you (and others) name your classes A, B, C etc. and your functions things like f1(), f2() etc. It makes life a lot easier for people answering your questions.
One way to avoid dynamic_cast is to have a virtual trampoline function "SpecialDoSomething" whose derived polymorphic implementation calls that particular derived class's "SpecialDxDoSomething()" which can be whatever non-base class name you desire. It can even call more than one function.