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.
Related
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);
...
}
I have two classes
class A {
public:
virtual void doStuff() = 0;
};
class B : public A {
int x;
public:
virtual void doStuff() override { x = x*2;} //just example function
};
And another class that modify and use data from the previous
class Foo {
A a;
public:
Foo::Foo(A &a_) : a(a_) {}
};
now I create the objects, and passes to the Foo class
B b;
// edit b attributes,
Foo foo(b);
So at the argument list for the class constructor I know there is not the problem of object slicing, because is a reference, but what is the case at the moment of assign the variable a(a_)?
Since I don't know how much time the object b is going to live I need to make a secure copy. I have a lot of different derived classes from A, even derived from the derived.
Will there be a object slicing?,
Is there a solution to this, or I need to pass pointers (don't want this approach)?
This causes slicing. C++ built in polymorphism only works with pointer/reference semantics.
In fact:
class Foo {
A a;
that won't even compile, because A is not a concrete class.
To fix this, first make virtual ~A(){}; and then pass smart pointers to A around. Either unique or shared.
Failing that you can use your own bespoke polymorphism. The easiers way is to stuff a pImpl smart pointer as a private member of a class and implement copy/move semantics in the holding class. The pImpl can have a virtual interface, and the wrapping class just forwards the non-overridable part of the behaviour to it.
This technique can be extended with the small buffer optimization, or even bounded size instances, in order to avoid heap allocation.
All of this is harder than just using the built in C++ object model directly, but it can have payoff.
To see a famous example of this, examine std::function<Sig> which is a value type that behaves polymorphically.
There will be object slicing with what you currently have. You're calling the A copy-constructor in Foo's constructor, and there aren't virtual constructors.
Having a member variable of type A only reserves enough space within an instance of Foo for an instance of A. There is only dynamic binding with pointers and references (which are pointers under the hood), not with member variables.
You would have to use pointers to get around this or you could rethink whether you really need a set-up like this.
Yes, there is slicing.
There has to be slicing, because a B does not fit inside a A, but it is an A that you are storing inside the class Foo. The B part is "sliced off" to fit; hence the name.
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?
Is it possible to have inheritance with no virtual methods? The compiler is saying that the following code is not polymorphic.
Example:
class A {
public:
int a;
int getA(){return a;};
}
class B : public A {
public:
int b;
int getB(){return b;};
}
In another class we are trying to downcast from an A object to a B object:
A *a = ...;
B *b = dynamic_cast<B*>(a)
but this gives the following compile-time error:
cannot dynamic_cast ... (source type is not polymorphic)
Syntax errors non-withstanding, you cannot dynamic_cast a non-polymorphic type. static_cast is the cast you would use in this case, if you know that it is in fact an object of the target type.
The reason why: static_cast basically has the compiler perform a check at compile time "Could the input be cast to the output?" This is can be used for cases where you are casting up or down an inheritance hierarchy of pointers (or references). But the check is only at compile time, and the compiler assumes you know what you are doing.
dynamic_cast can only be used in the case of a pointer or reference cast, and in addition to the compile time check, it does an additional run time check that the cast is legal. It requires that the class in question have at least 1 virtual method, which allows the compiler (if it supports RTTI) to perform this additional check. However, if the type in question does not have any virtual methods, then it cannot be used.
The simplest case, and probably worthwhile if you're passing pointers around like this, is to consider making the base class's destructor virtual. In addition to allowing you to use dynamic cast, it also allows the proper destructors to be called when a base class pointer is deleted.
You need at least one virtual method in a class for run-time type information (RTTI) to successfully apply dynamic_cast operator.
just make A destructor virtual (always do for any class just for safety).
yes, dynamic_cast for non-polymorphic types are not allowed. The base class shall have at least one virtual method. Only then that class can be called as polymorphic.
This article explains a similar example: http://www.cplusplus.com/doc/tutorial/typecasting/
A a;
B *b = dynamic_cast<B*>(a)
Here a is an object and b is a pointer.
Actually, upcasting and downcasting are both allowed in C++. But when using downcasting, 2 things should be pay attention to:
The superclass should has at least one virtual method.
Since superclass is "smaller" than subclass, one should use memory object carefully.
I have following classes.
class A
{
public:
void fun();
}
class B: public A
{
}
class C: public A
{
}
A * ptr = new C;
Is it ok to do something like below? Will i have some problems if introduce some virtual functions in the baseclass?
((B *)ptr)->fun();
This may look stupid, but i have a function that calls A's function through B and i don't want to change that.
You can't cast an A* pointing to Class C as a B* because Class C doesn't have any relation with Class B. You'll get undefined behavior which will probably be the wrong function called and stack corruption.
If you intended for class C to derive from class B then you could. However, you wouldn't need to. If class C doesn't have fun() defined, it will inherit A's. You didn't declare fun() virtual though so you'll get strange behavior if you even implement C::fun() or B::fun(). You almost certainly want fun() to be declared virtual.
I'm guessing here but I suspect the behavior of this might depend on the compiler you use and how it decides to organize the vf pointer table.
I'm also going to note that I think what you are doing is a bad idea and could lead to all kinds of nightmarish problems (use of things like static_cast and dynamic_cast are generally a good idea). The other thing is because fun() is defined in the base class (and it is not virtual) ptr->fun() will always call A::fun() without having to cast it to B*.
You don't have to do the casting (B*) ptr->fun(); since the fun() is already in the base class. both objects of class B or C will invoke the same fun() function in your example.
I'm not sure what happens when u override the fun() function in class B...
But trying to invoke function from another class (not the base class) is bad OO, in my opinion.
You can cast from A * to B *, and it should work if the original pointer was B *.
A* p = new B;
B* q = static_cast<B*>(p); // Just work (tm)
But in this case it is a C *, and it is not guaranteed to work, you will end with a dangling pointer, if you are lucky you will get an access violation, if not you man end up silently corrupting your memory.
A* p = new C;
B* q = static_cast<B*>(p); // Owned (tm)