Best practice with dynamic_cast and polymorphism - c++

I have a design problem that I am not sure how to handle in the best way. I want my code to be future proof and still not be to messy and complex (the plight of a geek).
Currently my design has the following setup
derived class D derived class E
^ ^
| |
derived abstract class B -> derived class C
^ ^
| |
Abstract Base class A
class B differs from class A, class D and class E differs from class B and C differs from class A.
As these classes differ I need to use the dynamic_cast operator.
A* a1 = new class C;
C* c1 = dynamics_cast<C*>(a1);
if(c1){ //Success!!!}
...
As you can see I will be wanting to use dynamic_cast a lot! I need to try and find a nice way of doing this that is not full of if() statements extra.
Is there a neat way of doing this? I seem to remember seeing something in a Scott Meyers book, but I am away from home and can not access it for a week or two.
Any references/examples would be much appreciated.
Also if need be I could make class B into an interface which would be a sort of solution
B* d1 = new D;
B* e1 = new E;
but not ideal.
NOTE: I have added this example to show my current design failure
class A {...};
class B: public A {
public:
virtual std::vector<objectType1*>& getObjectType1();
};
class C: public B {
private:
void newFunction();
};
A* c1 = new C();
std::vector<objectType1*> example = c1->getObjectType1(); // Wrong; need dyanmic_cast :-(
can not access getObjectType1() without dynamic_cast as the static type A does not know about this function. I need to rethink my design. Any ideas?

In a properly designed object hierarchy, the use of dynamic_cast is a fair rarity. Sure, it exists to cast up & down a polymorphic tree, but that doesn't mean you have to use it.
Think about this. Why would you need to use dynamic_cast, generally speaking? Because the base pointer you have doesn't provide the facilities you need, right? And what is the point of polymorphism? To provide different behavior for similar operations, where the behavior is chosen at run-time, right?
Aren't those two statements somewhat contradictory? If your object's interface is designed correctly, then you don't really care what kind of behavior is going to be employed when you call ->Foo() -- you just want to call ->Foo().
If you need to make frequent use of dynamic_cast, it's a code smell that tells you that there's something wrong with your interfaces. Maybe you're trying to shove too much in to one interface?

Related

is it possible to down cast from parent class pointer to child class pointer inside a second child class?

There are three classes a,b and c namely.
Both b and c are children of a.
Is there a way to downcast from a pointer of a to the pointer of b inside of class c?
Hope I explained myself correctly.
Thanks for the Help in advance.
The answer to your question "is it possible..." is yes.
However, the need for it indicates bad design. Anything you are going to do with the down-cast pointer should be done via virtual functions.
In rare cases that you need it (please explain your use case to see if it is one of those), you should use C++ dynamic_cast<>, and not a C-style cast.
The bigger issue in your design is - class c should NOT be aware of class b.
Class C : public A {
...
A* x1;
B* b1 = (B*)x1;
// or
A x2;
B* b2 = (B*)(&x2);
...
}

Why cannot reach derived class's member function using a base class pointer in C++? What's the design idea of it?

 
Using the base class pointer can reach the derived class content, in general,I think. Maybe I think it is like a train, as long as I find the head of it,I can reach all of them which is public.
 
However, when I try to do something like this, I got an error that the base class cannot find the derived class's member function. Although I use a base class pointer variable to record the derived class address, I think it can also reach derived class member function with the head of train. While the fact proved it cannot. So I wonder what the design idea of it. Why it is designed not like Python can do? What is the advantage of this design idea?
The error is prompted as blow:
Sketch map:
Demo code:
#include <iostream>
using namespace std;
class B{
public:
void helloB(){
cout << "hello B" << endl;
}
};
class C:public B{
public:
void helloC(){
cout << "hello C" << endl;
}
};
class A{
public:
B* t;
void helloA(){
t->helloC();
}
};
int main(){
A a;
C c;
a.t = &c;
a.helloA();
}
Why?
C++ is statically typed language. That is, it does type-checking at compilation time, not at runtime.
At compilation time, the compiler has no way of knowing that t (which it knows to have type B*) has a helloC method. The language is trying to prevent you from shooting yourself in the foot by invoking undefined behavior if the method doesn't exist.
In contrast, Python is a dynamic language that does not have static type checking.
There are tradeoffs from static- vs. dynamic-checking. Dynamic-checking is more flexible but usually means that you can't catch some errors unless you exercise all code paths at runtime. Static-checking helps catch errors early and allows for better optimized (i.e. faster) code. For example, when invoking A::helloA, if B::helloC existed, your program would not need to check first whether t has a helloC method; it would already have been proven at compilation time.
C++ is statically typed because its target audience are developers who want to optimize for speed.
In C++, what can you do instead?
To avoid this in C++, you instead must push your interface into the base class and make it a virtual method or perform a downcast to force a pointer (or reference) to a base class to be treated as a pointer/reference to the derived class. In this case, you could use static_cast:
void helloA(){
static_cast<C*>(t)->helloC();
}
which tells the compiler that you know with absolute certainty that t is actually a C*. This will add no runtime overhead, but no runtime overhead also means that there is no runtime checking that t is actually a C*.
A more general way to downcast is to use dynamic_cast:
void helloA(){
C* c = dynamic_cast<C*>(t);
if (c != null) {
c->helloC();
}
}
which will check at runtime whether t is actually a C*. Runtime checks have a runtime cost, of course.
Well, the compiler doesn't know anything about the object in question other than it's an instance of class B. You could have some other classes derived from B and they will fit everywhere class B can fit. Consider this: class B is more general thing (let's say an animal), while class C or any other class derived from B is some kind of animal. Let's say a dog or a bird. Let's assume all animals can make a noise, but only birds can lay an egg. Now you can have a set of animals and tell them all to make a sound, but you can't tell all of them to lay an egg. The compiler doesn't have an idea of egg-laying animal on this abstraction level. In your code the compiler can't be sure you're talking about an instance of class C.
My friend, you need to read a bit about inheritance in c++ or at least difference between c++ and python for inheritance.
From your example, it looks like you are asking a dog say Meow :D
Class C inherits from class B, not the other way, so method helloC, which is from class C, can't be called from an object of class B.

How to downcast a shared_ptr in the case of virtual inheritance?

Suppose I have a class C, inheriting from B, itself virtually inheriting from A:
class A {};
class B : virtual public A {};
class C : public B {};
Now suppose I have a std::shared_ptr<A> managing an object which I know for sure is of some class inheriting B (e.g., of class C), and I even happen to have it available as a raw B pointer, in a way equivalent to the minimal example below:
B * pb = new C;
std::shared_ptr<A> spa(pb);
Now I want to downcast the std::shared_ptr<A> to a std::shared_ptr<B>. I can't use static_pointer_cast because the inheritance is virtual. I could use dynamic_pointer_cast but it seems an overkill given that I already have the object available as a raw B pointer.
Is the following code the appropriate way to achieve my goal?
std::shared_ptr<B> spb(spa, pb);
It seems that yes, but I'd like some confirmation from someone who knows better (I never had to use the aliasing constructor before).
Is the following code the appropriate way to achieve my goal?
Yes. In both cases (your alternative and dynamic_pointer_cast), you get a shared_ptr who's operator-> will return a reference to a B. And in both cases, it is the object A which will have delete called upon it when all references are destroyed. In all ways they will behave the same.
Which also means that if you don't define a virtual destructor in A, then in both cases, your code will break upon the deletion of A.
That being said, there's nothing "overkill" about using a dynamic_pointer_cast in this circumstance.

C++ casting oddness

Let's use this simple class hierarchy:
class A
{
public:
virtual void Af() {};
};
class IB
{
public:
virtual void Bf() = 0;
};
class C : public A, public IB
{
public:
virtual void Bf() {}
void Cf() { printf("Cf"); }
};
An now some tests I have done, trying to understand static_cast and dynamic_cast:
1) C* c = new C();
2) A* a = static_cast<A*>(c);
3) IB* ib = static_cast<IB*>(c); //ib gets a different pointer than c because ib vtable is assigned
4) A* correctA = static_cast<A*>(static_cast<C*>(ib)); //Correct, but I must cast first to C and the to A from Interface
5) A* incorrectA = static_cast<A*>(ib); //Compiler error
6) A* correctA2 = dynamic_cast<A*>(ib); //Correct result
Now, some questions:
1) I have started to code in C++ since I moved to C# about 5 years ago. I'm surprised of the "ib" variable value in number 3. I expected it to be same pointer as "c" variable but instead the cast is assigning the value of the vtable of class "ib" in "c"
2) Why must I cast fist to C* and then to A* in 3 to get a correct value? This makes polimorphism useless in this case. Because I want to cast from the interface to the base type without knowing the real type. 5 shows that this is not possible with static_cast (I guess that this is checking the inheritance tree and concluding IB interface is not related to A* but they really are at runtime.
3) 6 gets a correct value into correctA2. I guess it does this correclty as I explain in question 2 because this can be resolved only at runtime.
Could you explain a bit this kind of behaviours and confirm my guessings? It is hard to come back from c# to c++ :D.
Cheers.
It looks like you may be trying to write C# in C++ in which case I suggest just sticking with C#. However I'll try to answer your questions:
1) (note this is implementation details that are probably right on most systems) In a multiply inherited derived class typically an implementation will have multiple virtual tables as the first items in the object memory. In this case a C would have first an A vtable and then an IB vtable. If you try to use the derived pointer as IB without changing its address, the IB would be using the A class's vtable resulting in havoc. Thus, the compiler fixes up the address for you.
2) This is just the way the language tells us static_cast will work: converting between parent/child objects, and a few other relationships like different integral types. dynamic_cast is needed to traverse sibling relationships directly.
3) Correct, since dynamic_cast offers more flexibility for polymorphic conversions you can use it to convert between a sibling relationship.
I should make a closing remark that using multiple inheritance in C++ to provide an implementation to an interface is not a common pattern. There may be alternate approaches if you ask your real question.
A static_cast requires there to be a single compile time relationship between the types that is more direct than any other relationship.
Imagine you had also defined
class D : public IB, public A
The relationship between A and IB through D would be no more nor less direct than through C. A static_cast can use the fact that the most direct relationship between IB and C is IB as a base class of C and can use the fact that the most direct relationship between C and A is A as a base class of C. But the relationship between IB and A through C cannot be know to be the most direct compile time relationship, so static_cast can't use it (by dynamic_cast can use it as the only available run time relationship).

How is C++'s multiple inheritance implemented?

Single inheritance is easy to implement. For example, in C, the inheritance can be simulated as:
struct Base { int a; }
struct Descendant { Base parent; int b; }
But with multiple inheritance, the compiler has to arrange multiple parents inside newly constructed class. How is it done?
The problem I see arising is: should the parents be arranged in AB or BA, or maybe even other way? And then, if I do a cast:
SecondBase * base = (SecondBase *) &object_with_base1_and_base2_parents;
The compiler must consider whether to alter or not the original pointer. Similar tricky things are required with virtuals.
The following paper from the creator of C++ describes a possible implementation of multiple inheritance:
Multiple Inheritance for C++ - Bjarne Stroustrup
There was this pretty old MSDN article on how it was implemented in VC++.
And then, if I do a cast:
SecondBase base = (SecondBase *) object_with_base1_and_base2_parents;
The compiler must consider whether to alter or not the original pointer. Similar tricky things with virtuals.
With non-virutal inheritance this is less tricky than you might think - at the point where the cast is compiled, the compiler knows the exact layout of the derived class (after all, the compiler did the layout). Usually all that happens is a fixed offset (which may be zero for one of the base classes) is added/subtracted from the derived class pointer.
With virutal inheritance it is maybe a bit more complex - it may involve grabbing an offset from a vtbl (or similar).
Stan Lippman's book, "Inside the C++ Object Model" has very good descriptions of how this stuff might (and often actually does) work.
Parents are arranged in the order that they're specified:
class Derived : A, B {} // A comes first, then B
class Derived : B, A {} // B comes first, then A
Your second case is handled in a compiler-specific manner. One common method is using pointers that are larger than the platform's pointer size, to store extra data.
This is an interesting issue that really isn't C++ specific. Things get more complex also when you have a language with multiple dispatch as well as multiple inheritance (e.g. CLOS).
People have already noted that there are different ways to approach the problem. You might find reading a bit about Meta-Object Protocols (MOPs) interesting in this context...
Its entirely down to the compiler how it is done, but I beleive its generally done througha heirarchical structure of vtables.
I have performed simple experiment:
class BaseA { int a; };
class BaseB { int b; };
class Descendant : public BaseA, BaseB {};
int main() {
Descendant d;
BaseB * b = (BaseB*) &d;
Descendant *d2 = (Descendant *) b;
printf("Descendant: %p, casted BaseB: %p, casted back Descendant: %p\n", &d, b, d2);
}
Output is:
Descendant: 0xbfc0e3e0, casted BaseB: 0xbfc0e3e4, casted back Descendant: 0xbfc0e3e0
It's good to realise that static casting does not always mean "change the type without touching the content". (Well, when data types do not fit each other, then there will be also an interference into content, but it's different situation IMO).