Can i safely call virtual functions after using static_cast on polymorphic class in situations like in the following code or is it UB?
#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo() \n"; }
};
class Derived : public Base
{
public:
virtual void foo() { std::cout << "Derived::foo() \n"; }
};
int main()
{
Base* derived = new Derived;
Derived* _1 = static_cast<Derived*>(derived);
_1->foo();
}
Yes, you can. Although I don't see the point of doing that in your specific example. Just calling it as
derived->foo();
without any casts would have produced exactly the same effect. I.e. some sort of static_cast in that case would be performed implicitly by the virtual call mechanism.
Note that your static_cast does not in any way suppress the "virtual" nature of the call.
That actually makes me wonder what your question is really about. Why would you even ask about it? What are you trying to do? In your code sample really representative of what you are trying to do?
If the compiler allows you to static_cast and at run-time the dynamic type of the object is as expected, then yes, you can. The question is why do you want to do that...
Yes, but as others have said, you don't need to cast the pointer to the derived type to call virtual functions.
However, it is usually safer to use dynamic_cast when dealing with inherited classes. Using dynamic_cast will generate the proper errors if the type information is incorrect at runtime.
Derived* d = dynamic_cast<Derived*>(derived); //safer, but still unnecessary in this situation
As written, that's going to work, basically because derived is a Derived*. So, all the cast is doing is telling the compiler what you already know. Then again, even without the static cast, you'll just end up with Derived::foo in your output. So, this is somewhat pointless. Still, you might need to do this in a situation where you're absolutely sure you know the actual instanced type of your variable and you need to access some non-virtual members for some reason. If you're using a badly designed class library, for instance...
But, in general, static downcasts are a bad idea. You might end up trying to downcast a variable that isn't a Derived*, in which case, calling virtual (or non-virtual) functions (or, in fact, using that pointer for almost any non-trivial operation) results in Undefined Behavior.
Related
I was studying Virtual Functions and Pointers. Below code made me to think about, why does one need Virtual Function when we can type cast base class pointer the way we want?
class baseclass {
public:
void show() {
cout << "In Base\n";
}
};
class derivedclass1 : public baseclass {
public:
void show() {
cout << "In Derived 1\n";
}
};
class derivedclass2 : public baseclass {
public:
void show() {
cout << "In Derived 2\n";
}
};
int main(void) {
baseclass * bptr[2];
bptr[0] = new derivedclass1;
bptr[1] = new derivedclass2;
((derivedclass1*) bptr)->show();
((derivedclass2*) bptr)->show();
delete bptr[0];
delete bptr[1];
return 0;
}
Gives same result if we use virtual in base class.
In Derived 1
In Derived 2
Am I missing something?
Your example appears to work, because there is no data, and no virtual methods, and no multiple inheritance. Try adding int value; to derivedclass1, const char *cstr; to derivedclass2, initialize these in corresponding constructors, and add printing these to corresponding show() methods.
You will see how show() will print garbage value (if you cast pointer to derivedclass1 when it is not) or crash (if you cast the pointer to derivedclass2 when class in fact is not of that type), or behave otherwise oddly.
C++ class member functions AKA methods are nothing more than functions, which take one hidden extra argument, this pointer, and they assume that it points to an object of right type. So when you have an object of type derivedclass1, but you cast a pointer to it to type derivedclass2, then what happens without virtual methods is this:
method of derivedclass2 gets called, because well, you explicitly said "this is a pointer to derivedclass2".
the method gets pointer to actual object, this. It thinks it points to actual instance of derivedclass2, which would have certain data members at certain offsets.
if the object actually is a derivedclass1, that memory contains something quite different. So if method thinks there is a char pointer, but in fact there isn't, then accessing the data it points to will probably access illegal address and crash.
If you instead use virtual methods, and have pointer to common base class, then when you call a method, compiler generates code to call the right method. It actually inserts code and data (using a table filled with virtual method pointers, usually called vtable, one per class, and pointer to it, one per object/instance) with which it knows to call the right method. So when ever you call a virtual method, it's not a direct call, but instead the object has extra pointer to the vtable of the real class, which tells what method should really be called for that object.
In summary, type casts are in no way an alternative to virtual methods. And, as a side note, every type cast is a place to ask "Why is this cast here? Is there some fundamental problem with this software, if it needs a cast here?". Legitimate use cases for type casts are quite rare indeed, especially with OOP objects. Also, never use C-style type casts with object pointers, use static_cast and dynamic_cast if you really need to cast.
If you use virtual functions, your code calling the function doesn't need to know about the actual class of the object. You'd just call the function blindly and correct function would be executed. This is the basis of polymorphism.
Type-casting is always risky and can cause run-time errors in large programs.
Your code should be open for extension but closed for modifications.
Hope this helps.
You need virtual functions where you don't know the derived type until run-time (e.g. when it depends on user input).
In your example, you have hard-coded casts to derivedclass2 and derivedclass1. Now what would you do here?
void f(baseclass * bptr)
{
// call the right show() function
}
Perhaps your confusion stems from the fact that you've not yet encountered a situation where virtual functions were actually useful. When you always know exactly at compile-time the concrete type you are operating on, then you don't need virtual functions at all.
Two other problems in your example code:
Use of C-style cast instead of C++-style dynamic_cast (of course, you usually don't need to cast anyway when you use virtual functons for the problem they are designed to solve).
Treating arrays polymorphically. See Item 3 in Scott Meyer's More Effective C++ book ("Never treat arrays polymorphically").
We can use Polymorphism (inheritance + virtual functions) in order to generalize different types under a common base-type, and then refer to different objects as if they were of the same type.
Using dynamic_cast appears to be the exact opposite approach, as in essence we are checking the specific type of an object before deciding what action we want to take.
Is there any known example for something that cannot be implemented with conventional polymorphism as easily as it is implemented with dynamic_cast?
Whenever you find yourself wanting a member function like "IsConcreteX" in a base class (edit: or, more precisely, a function like "ConcreteX *GetConcreteX"), you are basically implementing your own dynamic_cast. For example:
class Movie
{
// ...
virtual bool IsActionMovie() const = 0;
};
class ActionMovie : public Movie
{
// ...
virtual bool IsActionMovie() const { return true; }
};
class ComedyMovie : public Movie
{
// ...
virtual bool IsActionMovie() const { return false; }
};
void f(Movie const &movie)
{
if (movie.IsActionMovie())
{
// ...
}
}
This may look cleaner than a dynamic_cast, but on closer inspection, you'll soon realise that you've not gained anything except for the fact that the "evil" dynamic_cast no longer appears in your code (provided you're not using an ancient compiler which doesn't implement dynamic_cast! :)). It's even worse - the "self-written dynamic cast" approach is verbose, error-prone and repetitve, while dynamic_cast will work just fine with no additional code whatsoever in the class definitions.
So the real question should be whether there are situations where it makes sense that a base class knows about a concrete derived class. The answer is: usually it doesn't, but you will doubtlessly encounter such situations.
Think, in very abstract terms, about a component of your software which transmits objects from one part (A) to another (B). Those objects are of type Class1 or Class2, with Class2 is-a Class1.
Class1
^
|
|
Class2
A - - - - - - - -> B
(objects)
B, however, has some special handling only for Class2. B may be a completely different part of the system, written by different people, or legacy code. In this case, you want to reuse the A-to-B communication without any modification, and you may not be in a position to modify B, either. It may therefore make sense to explicitly ask whether you are dealing with Class1 or Class2 objects at the other end of the line.
void receiveDataInB(Class1 &object)
{
normalHandlingForClass1AndAnySubclass(object);
if (typeid(object) == typeid(Class2))
{
additionalSpecialHandlingForClass2(dynamic_cast<Class2 &>(object));
}
}
Here is an alternative version which does not use typeid:
void receiveDataInB(Class1 &object)
{
normalHandlingForClass1AndAnySubclass(object);
Class2 *ptr = dynamic_cast<Class2 *>(&object);
if (ptr != 0)
{
additionalSpecialHandlingForClass2(*ptr);
}
}
This might be preferable if Class2 is not a leaf class (i.e. if there may be classes further deriving from it).
In the end, it often comes down to whether you are designing a whole system with all its parts from the beginning or have to modify or adapt parts of it at a later stage. But if you ever find yourself confronted with a problem like the one above, you may come to appreciate dynamic_cast as the right tool for the right job in the right situation.
It allows you to do things which you can only do to the derived type. But this is usually a hint that a redesign is in order.
struct Foo
{
virtual ~Foo() {}
};
struct Bar : Foo
{
void bar() const {}
};
int main()
{
Foo * f = new Bar();
Bar* b = dynamic_cast<Bar*>(f);
if (b) b->bar();
delete f;
}
I can't think of any case where it's not possible to use virtual functions (other than such things as boost:any and similar "lost the original type" work).
However, I have found myself using dynamic_cast a few times in the Pascal compiler I'm currently writing in C++. Mostly because it's a "better" solution than adding a dozen virtual functions to the baseclass, that are ONLY used in one or two places when you already (should) know what type the object is. Currently, out of roughly 4300 lines of code, there are 6 instances of dynamic_cast - one of which can probably be "fixed" by actually storing the type as the derived type rather than the base-type.
In a couple of places, I use things like ArrayDecl* a = dynamic_cast<ArrayDecl*>(type); to determine that type is indeed an array declaration, and not someone using an non-array type as a base, when accessing an index (and I also need a to access the array type information later). Again, adding all the virtual functions to the base TypeDecl class would give lots of functions that mostly return nothing useful (e.g. NULL), and aren't called except when you already know that the class is (or at least should be) one of the derived types. For example, getting to know the range/size of an array is useless for types that aren't arrays.
No advantages really. Sometimes dynamic_cast is useful for a quick hack, but generally it is better to design classes properly and use polymorphism. There may be cases when due to some reasons it is not possible to modify the base class in order to add necessary virtual functions (e.g. it is from a third-party which we do not want to modify), but still dynamic_cast usage should be an exception, not a rule.
An often used argument that it is not convenient to add everything to the base class does not work really, since the Visitor pattern (see e.g. http://sourcemaking.com/design_patterns/visitor/cpp/2) solves this problem in a more organised way purely with polymorphism - using Visitor you can keep the base class small and still use virtual functions without casting.
dynamic_cast needs to be used on base class pointer for down cast when member function is not available in base class, but only in derived class. There is no advantage to use it. It is a way to safely down cast when virtual function is not overridden from base class. Check for null pointer on return value. You are correct in that it is used where there is no virtual function derivation.
I have a class that derives from a C struct. The class does not do anything special, other than initialization in the constructor, deinitialization function during the destructor, and a few other methods that call into C functions. Basically, it's a run-of-the-mill wrapper. Using GCC, it complained that my destructor was not virtual, so I made it that. Now I run into segfaults.
/* C header file */
struct A
{
/* ... */
}
// My C++ code
class B : public A
{
public:
B() { /* ... init ... */ }
virtual ~B() { /* ... deinit ... */ }
void do()
{
someCFunction(static_cast<A *>(this));
}
};
I was always under the assumption that the static_cast would return the correct pointer to the base class, pruning off the virtual table pointer. So this may not be the case, since I get a segfault in the C function.
By removing the virtual keyword, the code works fine, except that I get a gcc warning. What is the best work around for this? Feel free to enlighten me :).
Both the explicit and implicit conversion to A* are safe. There is neither need for an explicit cast, nor is it going to introduce vtables anywhere, or anything like that. The language would be fundamentally unusable if this were not the case.
I was always under the assumption that the static_cast would return
the correct pointer to the base class, pruning off the virtual table
pointer.
Is absolutely correct.
The destructor need be virtual only if delete ptr; is called where ptr has type A*- or the destructor invoked manually. And it would be A's destructor that would have to be virtual, which it isn't.
Whatever the problem is in your code, it has nothing to do with the code shown. You need to expand your sample considerably.
The destructor of base classes should be virtual. Otherwise, there's a chance that you run into undefined behavior. This is just a speculation, as the code is not enough to tell the actual reason.
Try making the destructor of A virtual and see if it crashes.
Note that a class and a struct are the same thing, other than default access level, so the fact that one's a class and the other a struct has nothing to do with it.
EDIT: If A is a C-struct, use composition instead of inheritance - i.e. have an A member inside of B instead of extending it. There's no point of deriving, since polymorphism is out of the question.
That's not how static_cast works. A pointer to an object continues to be the same pointer, just with a different type. In this case, you're converting a pointer to a derived type (B) into a pointer to the base type (A).
My guess is that casting the pointer does not actually change the pointer value, i.e., it's still pointing to the same memory address, even though it's been cast into an A* pointer type. Remember that struct and class are synonyms in C++.
As #Luchian stated, if you're mixing C and C++, it's better to keep the plain old C structs (and their pointers) as plain old C structs, and use type composition instead of inheritance. Otherwise you're mixing different pointer implementations under the covers. There is no guarantee that the internal arrangement of the C struct and the C++ class are the same.
UPDATE
You should surround the C struct declaration with an extern "C" specification, so that the C++ compiler knows that the struct is a pure C struct:
extern "C"
{
struct A
{
...
};
}
Or:
extern "C"
{
#include "c_header.h"
}
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 had a question about C++ destructor behavior, more out of curiosity than anything else. I have the following classes:
Base.h
class BaseB;
class BaseA
{
public:
virtual int MethodA(BaseB *param1) = 0;
};
class BaseB
{
};
Imp.h
#include "Base.h"
#include <string>
class BImp;
class AImp : public BaseA
{
public:
AImp();
virtual ~AImp();
private:
AImp(const AImp&);
AImp& operator= (const AImp&);
public:
int MethodA(BaseB *param1) { return MethodA(reinterpret_cast<BImp *>(param1)); }
private:
int MethodA(BImp *param1);
};
class BImp : public BaseB
{
public:
BImp(std::string data1, std::string data2) : m_data1(data1), m_data2(data2) { }
~BImp();
std::string m_data1;
std::string m_data2;
private:
BImp();
BImp(const BImp&);
BImp& operator= (const BImp&);
};
Now, the issue is that with this code, everything works flawlessly. However, when I make the destructor for BImp virtual, on the call to AImp::MethodA, the class BImp seems to have its data (m_data1 and m_data2) uninitialized. I've checked and made sure the contained data is correct at construction time, so I was wondering what the reason behind this could be...
Cheers!
Edit: param1 was actually a reference to B in MethodA. Looks like I over-sanitized my real code a bit too much!
Edit2: Re-arranged the code a bit to show the two different files. Tested that this code compiles, a well. Sorry about that!
If you are casting between related types as you do in this case, you should use static_cast or dynamic_cast, rather than reinterpret_cast, because the compiler may adjust the object pointer value while casting it to a more derived type. The result of reinterpret_cast is undefined in this case, because it just takes the pointer value and pretends it's another object without any regard for object layout.
MethodA takes its parameters by value. This means a copy is passed (and the copy has to be destroyed). That's my best guess for why you might have a BImpl being destroyed that you didn't expect to be, but I don't see what the virtual or non-virtual nature of A's destructor could possibly have to do with it.
But this code can't compile - you use class B in declaring the virtual function in A, but B isn't defined until later. And I don't know what's going on with that cast - you can't reinterpret_cast class types. Perhaps if you work up a test case which demonstrates your issue, and post that?
There's a lot of iffy stuff in this code, so I'm amazed that it works or compiles in any case.
Passing parameters by value instead of reference to MethodA
Casting a B to a BImp via reinterpret_cast -- bad idea! If you're going to cast in that direction, dynamic_cast is the safest.
I fail to see how you're supposed to get a BImp out of a B. You are not invoking any constructors, and you have none that could be invoked that would accept a B. Your default constructor for BImp is private, and assigning a B that has no data, casted to a BImp that still has no data, to a BImp, still isn't going to give you any data!
Several comments:
Your base classes should have virtual destructors so the derived class' dtor is called instead of the just the base class dtor when the object is deleted.
MethodA taking a BaseB pointer as a parameter only to have the pointer reinterpreted as a BImp (a derived class of BaseB) is dangerous. There is no guarantee something else other than BImp is passed to MethodA. What would happen if just a BaseB object was to MethodA? Potentially lots of bad things, I would suspect.
I'm guessing your code "works flawlessly" because you only pass BImp to MethodA. If you are only passing BImp to MethodA then make the signature match the intent (this has the added benefit of removing that awful reinterpret call).
Your code is ill-formed. It is not valid C++. In C++ language reinterpret_cast can only be used to cast between pointer types, reference types, to perform pointer-to-integer conversions (in either direction).
In your code you are trying to use reinterpret_cast to convert from type B to type BImp. This is explicitly illegal in C++. If your compiler allows this code, you have to consult your compiler's documentation in order to determine what's going on.
Other replies already mentioned "slicing". Keep in mind that this is nothing more than just a guess about specific non-standard behavior of your specific compiler. It has nothing to do with C++ language.