I have a cpp code where in class c is derived from class b and class b is derived from class a.
Now class b has some public data member. So I am creating a instance of class c on heap passing its pointer to another class as pointer to a and there it is downcasting that pointer to pointer of class b and then printing public variables of class b.
Is this a valid downcasting. I am asking because just change of compiler has broken this working code.
I am including below code snippet which captures problem I am having.
#include <iostream>
using namespace std;
class grand
{
};
class parent : public grand
{
public : parent(){i=0;}
int i;
parent(int j){ i = j;}
void set(int j){i = j;}
};
class child : public parent{
public: child(){};
};
void print ( grand* ptr)
{
parent *p = (parent*) ptr;
std::cout << std::endl << p->i << std::endl;
}
int main() {
// your code goes here
child c;
c.set(9);
print(&c);
return 0;
}
Thanks
Is this a valid downcasting.
Yes. Your cast internally applies static_cast, which, according to §5.2.9/11, will give you the right result. If the argument for ptr doesn't point to a parent, the result of the cast is undefined - and so would the execution of the following code be.
Downcasting of polymorphic types in C++ works via dynamic_cast. Your grand class above isn't polymorphic - you have to add at least a virtual destructor to grand to make it polymorphic. Otherwise you'll get a compiler error with the following code.
parent *p = dynamic_cast<parent*>(ptr); // Once grand is polymorphic...
And check whether the result, p, is non-zero. Only this method reveals (at runtime) whether the cast worked! All others either invoke undefined behavior or undefined, non-zero values.
Some notes:
Downcasting is almost always a sign of bad design. Avoid it if possible, using - for example - virtual (print) functions.
print should take a pointer to const since it doesn't modify any data members.
Your code, as written, is in fact valid, but there are a bunch of observations I'd like to make. Note that it's valid only because the object you pass to print is a parent or further derived class.
Then note that since you have to cast it the print function it's much safer to just change the function signature to take aparent instead of a grand and then you don't have to worry about the casting.
Then note that a likely cause of your problem is that in the file that does the cast, the compiler doesn't see the relationship between grand and parent so your C-style cast falls back to reinterpret_cast which is not what you want. If you can't change the signature of print at least change the cast to static_cast (or possibly dynamic_cast, but you can't do that in your example because the classes aren't polymorphic) so that the compiler will fail to compile when it can't see the class relationship.
Instead of a C-style cast you should apply a dynamic_cast or a at least a static_cast if you compile without RTTI (runtime type information) for some reason.
Your C-style cast is the same as a reinterpret_cast, which essentially interprets the memory pointed to as if an object of type parent would have been constructed there. But, every compiler may have a different memory layout of derived classes, thus that may work in some circumstances but there's no guarantee.
Related
My C++ is a bit rusty and I don't remember everything in the standard.
I have a void*. In one specific function it is either a class that inherits Alpha or one that inherits Beta. Both base classes have virtual functions. However I can't seem to tell which is which
class Alpha {
public:
virtual void Speak() { printf("A"); }
};
class Beta {
public:
virtual void Speak() { printf("B"); }
};
int main(){
//BAD CODE WILL PRINT TWICE
void *p = new Alpha;
Alpha*a = dynamic_cast<Alpha*>((Alpha*)p);
Beta*b = dynamic_cast<Beta*>((Beta*)p);
if(a)
a->Speak();
if(b)
b->Speak();
return 0;
}
How do I figure out which class is which? There are 100's of classes in this codebase that gets converted to void. Most of them inherit 5 base classes however I'm not eager to find out. Is the only solution inheriting from something like class Dummy {public: virtual void NoOp(){}}; and cast to Dummy before using dynamic cast? Is this safe? I'm hoping there's a better solution but I can't think of anything else.
The only thing you can do with a void* pointer is to cast it back to exactly the same type as the pointer that was cast to void* in the first place. The behaviour on doing anything else is undefined.
What you could do in your case is define
class Base
{
public:
virtual ~Base() = default; // make me a polymorphic type and make
// polymorphic delete safe at the same time.
};
and make this the base class for Alpha and Beta. Then pass a Base* pointer around rather than a void* one, and take your dynamic_casts directly on p.
Note further that if you declared virtual void Speak() = 0; in Base, then your code in main would become simply
int main(){
Base* p = new Alpha;
p->Speak();
delete p; // ToDo - have a look at std::unique_ptr
}
As a rule of thumb, casts of any kind are undesirable.
The expression Alpha*a = dynamic_cast<Alpha*>((Alpha*)p); first casts p to Alpha* with an explicit c style cast. Then, that resulting Alpha* is passed through dynamic_cast<Alpha*>. Using dynamic_cast<T*> on a T* pointer (a pointer of the same type as you are trying to cast to) will always provide the input pointer. It cannot be used to confirm that the pointer is valid. From cppreference for dynamic_cast<new_type>(expression) :
If the type of expression is exactly new_type or a less cv-qualified version of new_type, the result is the value of expression, with type new_type.
As a result, the code will always compile and run and the type system will not protect you. But the resulting behavior is undefined. In the case of Beta*b = dynamic_cast<Beta*>((Beta*)p); you tell the compiler to trust that p is a Beta* but this is not true. Dereferencing the resulting pointer is undefined behavior and dynamic_cast cannot protect you from this mistake.
If you try to remove the explicit type conversion, you will get a compiler error. dynamic_cast requires a pointer or reference to a complete type, and void is not a complete type. You will have to find a way to track the actual type pointed to yourself and explicitly convert p to that pointer type before using dynamic_cast. Though at that point, if you already know the type to cast to, it may no longer be necessary.
Consider using a common base type instead or maybe using std::variant or std::any if need be.
If you use a C-style cast to convert to Alpha*, similar to a static_cast before using dynamic cast, then the dynamic cast as no effect. here your code runs because the two classes have the same interface but in reality this is undefined behaviour.
Usually, you want to use dynamic cast to upcast/downcast from/to a base class to/from it's derived class.
For example, if we add a base interface, then convert the void * pointer to this base class and then use dynamic cast to attempt Up-casting, the code works as expected and only print once.
#include <stdio.h>
class Speaker {
public:
virtual void Speak() = 0;
};
class Alpha: public Speaker {
public:
virtual void Speak() { printf("A"); }
};
class Beta: public Speaker {
public:
virtual void Speak() { printf("B"); }
};
int main(){
void *p = new Alpha;
// Convert to base type, using static_cast
Speaker *s = static_cast<Speaker *>(p);
// Attempt Upcasts
Alpha*a = dynamic_cast<Alpha*>(s);
Beta*b = dynamic_cast<Beta*>(s);
// See if it worked
if (a)
a->Speak();
if (b)
b->Speak();
return 0;
}
Outputs: A
You must know the type from which the void pointer was converted from. If you don't know the dynamic type, then you must create the void pointer from the pointer to base. If you don't know the type of the pointer which the void pointer was created from, then you cannot use the void pointer.
Given that the void pointer was converted from Alpha*, you can convert it back using a static cast:
auto a_ptr = static_cast<Alpha*>(p);
You can then use dynamic_cast to convert to a derived type.
if(auto d_ptr = dynamic_cast<DerivedAlpha*>(a_ptr)) {
// do stuff with DerivedAlpha
In case the dynamic type isn't DerivedAlpha, the dynamic cast would safely return null. You cannot dynamic cast away from a type hierarchy. Since Alpha and Beta are not related by any inheritance structure, they cannot be dynamically casted mutually.
I feel this could be explained more simply than what is said already.
Basically, casting from a raw void*, none of the "smarts" of dynamic_cast can apply because it has nothing to go on, it just gives you back the same pointer. You need to have some shared parent class type or something as your pointer type (*p) so it knows how to read the memory and determine actual type.
In your case, you are "lucking out" that the memory layout of Alpha and Beta is the same so calling speak on Beta* ends up calling Alpha::speak(). As others said this is UB and if the classes were more different you would likely seg-fault or corrupt the stack.
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").
I've recently came across this strange function in some class:
void* getThis() {return this;}
And later in the code it is sometimes used like so: bla->getThis() (Where bla is a pointer to an object of the class where this function is defined.)
And I can't seem to realize what this can be good for. Is there any situation where a pointer to an object would be different than the object's this (where bla != bla->getThis())?
It seems like a stupid question but I wonder if I'm missing something here..
Of course, the pointer values can be different! Below an example which demonstrates the issue (you may need to use derived1 on your system instead of derived2 to get a difference). The point is that the this pointer typically gets adjusted when virtual, multiple inheritance is involved. This may be a rare case but it happens.
One potential use case of this idiom is to be able to restore objects of a known type after storing them as void const* (or void*; the const correctness doesn't matter here): if you have a complex inheritance hierarchy, you can't just cast any odd pointer to a void* and hope to be able to restore it to its original type! That is, to easily obtain, e.g., a pointer to base (from the example below) and convert it to void*, you'd call p->getThis() which is a lot easier to static_cast<base*>(p) and get a void* which can be safely cast to a base* using a static_cast<base*>(v): you can reverse the implicit conversion but only if you cast back to the exact type where the original pointer came from. That is, static_cast<base*>(static_cast<void*>(d)) where d is a pointer to an object of a type derived from base is illegal but static_cast<base*>(d->getThis()) is legal.
Now, why is the address changing in the first place? In the example base is a virtual base class of two derived classes but there could be more. All subobjects whose class virtually inherits from base will share one common base subject in object of a further derived class (concrete in the example below). The location of this base subobject may be different relative to the respective derived subobject depending on how the different classes are ordered. As a result, the pointer to the base object is generally different from the pointers to the subobjects of classes virtually inheriting from base. The relevant offset will be computed at compile-time, when possible, or come from something like a vtable at run-time. The offsets are adjusted when converting pointers along the inheritance hierarchy.
#include <iostream>
struct base
{
void const* getThis() const { return this; }
};
struct derived1
: virtual base
{
int a;
};
struct derived2
: virtual base
{
int b;
};
struct concrete
: derived1
, derived2
{
};
int main()
{
concrete c;
derived2* d2 = &c;
void const* dptr = d2;
void const* gptr = d2->getThis();
std::cout << "dptr=" << dptr << " gptr=" << gptr << '\n';
}
No. Yes, in limited circumstances.
This looks like it is something inspired by Smalltalk, in which all objects have a yourself method. There are probably some situations in which this makes code cleaner. As the comments note, this looks like an odd way to even implement this idiom in c++.
In your specific case, I'd grep for actual usages of the method to see how it is used.
Your class can have custom operator& (so &a may not return this of a). That's why std::addressof exists.
I ran across something like this many (many many) years ago. If I recall correctly, it was needed when a class is manipulating other instances of the same class. One example might be a container class that can contain its own type/(class?).
That might be a way to override the this keyword.
Lets say that you have a memory pool, full initialized at the start of your program, for instance you know that at any time you can deal with a max of 50 messages, CMessage.
You create a pool at the size of 50 * sizeof(CMessage) (what ever this class might be), and CMessage implements the getThis function.
That way instead of overriding the new keyword you just override the "this", accessing the pool.
It can also mean that the object might be defined on different memory spaces, lets say on a SRAM, in boot mode, and then on a SDRAM.
It might be that the same instance will return different values for getThis through the program in such a situation, on purpose of course, when overriden.
I've wrote a piece of code, but I am confused with its output:
#include <iostream>
using namespace std;
class B{
public:
virtual void foo() {cout << "B::foo" << endl;}
};
class D:public B{
public:
virtual void foo() {cout << "D::foo" << endl;}
void disp() {cout << "D::disp" << endl;}
};
void func(B *pb){
D *pd1 = static_cast<D*>(pb);
pd1->foo();
pd1->disp();
}
int main(int argc, char *argv[])
{
B* pb = new B();
func(pb);
return 0;
}
The output is:
B::foo
D::disp
But as far as I know, pb points to type B. And there's no function named disp() in it? So, why could it get access to disp() function in class D?
Since disp() doesn't access any of the members of the class, it is in principle the same as if it were declared in the global namespace instead of in class, so there are no negative side effects to calling it, even though the instance is not of the right class.
What are you doing is downcasting a pointer of a base class to a pointer of the derived class, even though it was not initialized as such. If disp() tried to access class members that were in D but not in B, you would probably run into segfaults.
Bottom line: don't use static_cast for downcasting unless you're absolutely sure the pointer is actually pointing to an instance of the derived class. If you're unsure, you can use dynamic_cast which fails in the event of mismatch (but there is the overhead of RTTI, so avoid it if you can).
dynamic_cast will return nullptr if the cast is incorrect or throw a std::bad_cast
exception if it casts references, so you will know for sure why it fails instead of possible memory corruption bugs.
The line:
D *pd1 = static_cast<D*>(pb);
Will make the cast regardless if the source pointer is B* or D*. In your case the result will be pointer that points to an object of a wrong type. Method disp will work because it is not using any data member or virtual function of the class D. In more complex case this will lead to unstable behaviour or a crash.
Your objects are polimorphic. You should use the dynamic_cast instead.
What's important in this context, I believe, is that the member function disp() isn't tucked away inside all objects of type D. It's a single function that exists in one place. And whether any object will try to call call disp() is decided by the code.
Your static_cast will produce what the compiler considers a pointer to D regardless of what pointer you pass it. And once you have a pointer to D, the compiler will let you attempt to call disp().
Put another way, static_cast will not protect you from casting a pointer incorrectly.
You did something very bad when you cast a pointer to an object allocated as a B to a pointer to a derived class D. Here's what the standard says, emphasis mine:
5.2.9 Static Cast
If the rvalue of type “pointer to cv1 B” points to a B that is actually a sub-object of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.
You've invoked undefined behavior by doing that static_cast. The compiler and runtime can do anything and still be compliant when the program invokes undefined behavior.
You need to understand the difference between the various types of C++ casts.
You're using a static cast here, which is the same as saying, "I don't really care if it's actually of that type or not - just try your best".
In this case, you want to know if your pointer is actually of the derived type you're casting it to. You should use a dynamic_cast. This cast will succeed only if the pointer is of the correct type. That means, that if it fails, it will return a NULL pointer.
The behavior you're seeing is what happens when you don't use the right cast for the job, which, while you can try to explain it, is something you really should avoid because it falls in the domain of undefined behavior. In other words, you cannot expect the same side effects across compilers or even different versions of the same compiler. In other words, avoid it.
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.