Say that I have the following code, is it safe to use?
Base class:
class B
{
public:
B(bool isDerived = false) : m_isDerived(isDerived) {}
bool isDerived() { return m_isDerived; }
private:
bool m_isDerived;
}
Derived class:
class D : public B
{
public:
D() : B(true) {}
}
Code:
B* b = new B(); // Create new base class
D* unknown = static_cast<D*>(b); // Cast the base class into a derived class
if (unknown->isDerived()) // Is this allowed?
// unknown is a D and can be used as such
else
// unknown is not a D and can not be used
Can I safely call unknown->isDerived() even though unknown is really a B in this case?
We make the assumption that unknown NEVER contains anything other than a B* or D* and that we NEVER do anything with unknown until isDerived() have been checked on it.
Edit:
Given the questions I will try to explain the reason why I'm trying to do this:
So essentially I have a Windows tree control which of course can't be directly connected to the c++ tree structure I'm using to store my data. So I have to reinterpret_cast my data to a DWORD_PTR that is stored together with each node in the tree control so I have a connection between the two. My tree structure consists of either the base type (a normal node) or the derived type (a node with more info in it that should be handled differently). The pointers to these are reinterpret_cast:ed and put in the tree control.
Now, when I'm stepping through the tree control I want to act on the nodes which are of the derived type, so I want to reinterpret_cast the DWORD_PTR into a derived type. But to be entirely correct I should reinterpret_cast it to a base type first (I guess?), and then downcast it to the derived type if it is a derived type. However I thought I could make it a bit simpler by reinterpret_cast it into a derived type immediately and then check via the function if it really is a derived type. If it wasn't I do nothing more with it. In my mind the base class data in the pointer should be at the same memory location no matter how much derived it is, but I might be wrong which is why I ask here.
I wanted to make the question clearer by not involving Windows in it, but what I want in reality would be something closer to this:
B* b1 = new B();
B* b2 = new D();
DWORD_PTR ptr1 = reinterpret_cast<DWORD_PTR>(b1);
DWORD_PTR ptr2 = reinterpret_cast<DWORD_PTR>(b2);
D* unknown = reinterpret_cast<D*>(ptr1 /* or ptr2 */); // Safe?
unknown->isDerived(); // Safe?
Essentially no matter what I do it's still unsafe at some level as I must reinterpret_cast the data.
Can I safely call unknown->isDerived() even though unknown is really a
B in this case?
First of all, why would you do this? You could just call b->isDerived() and then do the downcasting.
Now, while premature and likely invalid downcast yields an undefined behavior (and should be universally despised) in this case it should work. Neither B nor D have implicit data members that might change the relative offset of m_isDerived and the address of isDerived member function is constant.
So yeah, it should work. If should is good enough for you.
EDIT: You can place a few tests to make sure offsets are same:
#include <cstddef> // for offsetof macro
#include <cassert> // for assert
#define offsetofclass(base, derived) ((static_cast<base*>((derived*)8))-8)
class Test
{
public:
Test()
{
assert(offsetofclass(B, D) == 0);
// you'll need to befriend Test with B & D to make this work
// or make the filed public... or just move these asserts
// to D's constructor
assert(offsetof(B, m_isDerived) == offsetof(D, m_isDerived));
}
};
Test g_test;
This will get executed on startup. I don't think it can be turned into a static assertion (executed and compile time).
Given your
class D : public B
and
B* b = new B(); // Create new base class
D* unknown = static_cast<D*>(b);
Formally this is Undefined Behavior, but, as long as only B things are accessed there's no technical reason why it should not work. Typically it's done in order to gain access to otherwise inaccessible B things, such as std::stack<T>::c. However there are better ways to do that, including the member function pointer trick.
Regarding
B(bool isDerived = false) : m_isDerived(isDerived) {}
that's very brittle and unsafe.
Instead class B should have a virtual member. Then you can use dynamic_cast and typeid. This is commonly known as RTTI, Run-time Type Information.
However, on the third and gripping hand, the relevant functionality should be made available via class B so that no downcasting is necessary.
As you have pointed out yourself, the only generally correct approach for storing an arbitary hierarchy in a single, opaque pointer is to go via the base class. So, first make your hierarchy:
struct Base { virtual ~Base(){}; /* ... */ };
struct FooDerived : Base { /* ... */ };
struct BarDerived : Base { /* ... */ };
struct ZipDerived : Base { /* ... */ };
You will now exclusively transform between a Base* and whatever raw pointer type you have. Strictly speaking, you can only store pointers in either a void* or a uintptr_t, but let's assume that your DWORD_PTR is wide enough.
If we wrap everything in a function, the upcasting is already taken care of:
void marshal_pointer(Base const * p, DWORD_PTR & dst)
{
static_assert(sizeof(DWORD_PTR) == sizeof(void *), "Not implementable");
dst = reinterpret_cast<DWORD_PTR>(p);
}
The return direction is just as easy:
Base * unmarshal_pointer(DWORD_PTR src)
{
static_assert(sizeof(DWORD_PTR) == sizeof(void *), "Not implementable");
return reinterpret_cast<Base *>(src);
}
All the actual polymorphic behaviour should be implemented in terms of virtual functions if possible. Manual dynamic_casts should be your last resort (though occasionally they're appropriate):
Base * p = unmarshal_pointer(weird_native_windows_thing);
p->TakeVirtualAction();
Related
If we compose calls to dynamic_cast and reach back to the original type on a pointer value, does C++ guarantee to preserve the value, assuming no dynamic_cast fails, i.e., does not return a nullptr?
I looked at the "Memory Layout in Virtual Inheritance" section in https://www.cprogramming.com/tutorial/virtual_inheritance.html. This gave me a decent idea of how it can be implemented. From the looks of it, it seems impossible to get a different address. However, it is only one such implementation, I just want to be sure that no conforming implementation can return a different address than the original.
#include <cassert>
struct A { virtual ~A() {} };
struct B : virtual public A {};
struct C : virtual public A {};
struct D : public B, public C {};
int main()
{
B* b = new D();
C* c = dynamic_cast<C*>(b);
if (c != nullptr)
{
B* bp = dynamic_cast<B*>(c);
assert(bp == b); // Will this assert ever fire?
}
return 0;
}
A more general case:
A* a = ...
dynamic_cast<A*>(dynamic_cast<B*>(...(a)...)) is `a` or nullptr
I ran the above code with gcc8 and clang9 and they don't fire the assert.
Does side-casting to and from sibling types preserve addresses in C++?
Dynamic casting produces a pointer to the base / derived object, and that object has exactly one address. This applies to side casting as much as down casting.
Note that side cast may fail if the base is ambiguous due to having multiple non-virtual bases of the same type. Your example does not have such ambiguity. In such case, null will be returned.
Can any operation change the layout of the object during run-time?
No. Layout of all objects is set in stone at their creation. In standard C++, the layout of all types is set in stone already on compilation, although there are language extensions such as flexible array member which can relax this.
I'm working with a library written in C, which does inheritance like so:
struct Base
{
int exampleData;
int (function1)(struct Base* param1, int param2);
void (function2)(struct Base* param1, float param2);
//...
};
struct Derived
{
struct Base super;
//other data...
};
struct Derived* GetNewDerived(/*params*/)
{
struct Derived* newDerived = malloc(sizeof struct Derived);
newDerived->super.function1 = /*assign function*/;
newDerived->super.function2 = /*assign function*/;
//...
return newDerived;
}
int main()
{
struct Derived *newDerieved = GetNewDerived(/*params*/);
FunctionExpectingBase((struct Base*) newDerived);
free(newDerived);
}
It is my understanding this works because the pointer to Derived is the same as the pointer to the first member of Derived, so casting the pointer type is sufficient to treat an object as its "base class." I can write whatever gets assigned to function1 and function2 to cast incoming pointer from Base* to Derived* to access the new data.
I am extending functionality of code like this, but I am using a C++ compiler. I'm wondering if the below is equivalent to the above.
class MyDerived : public Base
{
int mydata1;
//...
public:
MyDerived(/*params*/)
{
function1 = /*assign function pointer*/;
function2 = /*assign function pointer*/;
//...
}
//...
};
int main()
{
MyDerived *newDerived = new MyDerived(/*params*/);
FunctionExpectingBase( static_cast<Base*>(newDerived) );
delete newDerived;
}
Can I expect the compiler to lay out the memory in MyDerived in the same way so I can do the same pointer cast to pass my object into their code? Or must I continue to write this more like their C architecture, and not take advantage of the C++ compiler doing some of the more tedious bits for me?
I'm only considering single inheritance for the scope of this question.
According to Adding a default constructor to a base class changes sizeof() a derived type and When extending a padded struct, why can't extra fields be placed in the tail padding? memory layout can change even if you just add constructor to MyDerived or make it non POD any other way. So I am afraid there is no such guarantee. Practically you can make it work using proper compile time asserts validating the same memory layout for both structures, but such solution does not seem to be safe and supported by standard C++.
On another side why your C++ wrapper MyDerived cannot inherit from Derived? This would be safe (as it can be safe when Derived is casted to Base and back, but I assume that is out of your control). It may change initialization code in MyDerived::MyDerived() to more verbose, but I guess that is small price for proper solution.
For your problem it does not really matter since the "client" code only cares about having a valid Base* pointer: they aren't going to downcast it in Derived or whatever, or copy it.
I tried this which didn't work:
void Map::OnLMClick(short xPos, short yPos)
{
SObject* pSObject = pEditWindow->GetSelectedItem();
if (pSObject==SOTile)
{
/* Do */
I tried this as a test:
SObject* EditorWindow::GetSelectedItem()
{
return pSOTile[1]; //pSOTile[1] is a valid pointer, member of EditorWindow
}
SOTile class is a child of base class SObject. So, is it possible to create a Base* to get one of its child's* returned and then have the program react differently depending of what child it returned? If it is the case, how do I then have access to members of it's child that are not members of base?
If your types are polymorphic (i.e. if they have at least one virtual function), you can use dynamic_cast:
Base* pObject = get_object(); // May return a pointer to Derived
Derived* pDerived = dynamic_cast<Derived*>(pObject);
Notice, that dynamic downcasts are sometimes an indicator of bad design. Try to think if a better arrangement of virtual functions in your hierarchy would help.
Without knowing the concrete application domain, it is not possible for me to give more concrete advices.
dynamic_cast operator performs a special checking when a class is polymorhic.
SOTile* pSOTile = dynamic_cast<SOTile*>(pSObject);
if (pSOTile)
{
/* Do */
}
Since SOTile is a pointer to a type that derives from SObject, you should not need to cast at all, since the compiler should be able to automatically resolve an SObject pointer from the derived pointer and then compare the two SObject pointers together (the same way that you can assign a derived pointer to a base pointer without type-casting). Some compilers, like Borland's, support that just fine, eg:
class Base
{
};
class Derived : public Base
{
};
Derived *d = ...;
Base *b = ...;
if (b == d) // <-- compiles fine
However, if for whatever reason your compiler does not allow that, you can manually cast the derived pointer using static_cast (don't use dynamic_cast to cast the base pointer):
if (pSObject == static_cast<SObject*>(SOTile))
If SOTile is not a pointer to a type that derives from SObject, static_cast will fail at compile-time.
I wouldn't recommend to use dynamic_cast. Instead, you can implement that different behavior in different child class. Sometimes called as "template method" pattern
In my project I have a scenario like suppose:
1) BaseClass is an interface which derives from a parent class IFlow
2) ChildClass derives from it ie from Base class
3) In childClass Init function I am using dynamic_cast to cast the objet of IFlow to BaseClass which is as shown below:
void ChildClass::init()
{
IFlow* pFlow = someMethod(); //it returns the IFlow object pointer
//this works for static cast but fails for dynamic cast
BaseClass *base = dynamic_cast<BaseClass*>(pFlow) ;
}
In the above code the 2nd line of dynamic _cast returns zero but if the dynamic_cast is changed to static_cast then the code works as expected .
Please advice
dynamic_cast will "not work" in two instances:
You have somehow compiled your code without RTTI. Fix your compiler settings.
The entire purpose of dynamic_cast is to ensure that the cast actually works. Casting from child to parent always works because every child of some type is guaranteed to be that type (the whole "all dogs are animals, but not all animals are dogs" thing). Casting from a parent to a child can fail if the object is not actually that child type. dynamic_cast will return a null pointer if the IFlow you give it is not actually a BaseClass.
Furthermore, your static_cast does not work. It simply returns a value. A value which, if you ever use it, results in undefined behavior. So it only "works" in the sense that it returned a value you could attempt to use.
So one of these two things happened. Which one is up to you to find, since you didn't give us the implementation of someMethod.
A dynamic_cast<> returns null (zero) if the cast is not legal. In this case it's doing what you want: there is a problem somewhere in your inheritance tree. (The static_cast<> "works" only because it's a sledgehammer; it forces the cast at compile time without any knowledge of the type that the pointer will actually have at runtime.)
if it like this?:
class A
{
public:
A(){a = 0;};
virtual ~A(){};
protected:
int a;
};
A *GetAInstance();
class B : public A
{
public:
B() : A() {b = 1;};
virtual ~B(){};
protected:
int b;
};
class C: public B
{
public:
C() : B() {};
~C(){};
void CheckA()
{
A *pA = GetAInstance();
B *pB = dynamic_cast<B*>(pA); --> Here pB is NULL.
B *pB2 = static_cast<B*>(pA);
};
};
A *GetAInstance()
{
A *pA = new A();
return pA;
};
int _tmain(int argc, _TCHAR* argv[])
{
C *pC = new C();
pC->CheckA();
return 0;
}
This is because you are trying to set a parent pointer to its child pointer. In dynamic_cast it thinks it is not safe, so it set the child pointer to NULL, you can see pB above which is NULL. For child class may have more functions/member variables, you call these new functions/member variables would cause run time error. But static_cast doesn't care this, it is only a compiler time check not run time check. static_cast only cares if they have some relation ship. If they have, static_cast convert the pointer even doesn't care run time error. Please run this small sample and check pB2 is not NULL. :)
Hope useful. Thanks! :)
What type is being returned by someMethod()? It needs to be derived from BaseClass to allow dynamic_cast to work. You can't cast downwards if it's not the correct type.
Static cast works at compile time and the compiler will just turn the pointer over.
I am having trouble with forcing data type changes has on my own objects. I have a base class say A and two classes derived from A called B and C. I pass objects B and C to a function that checks which type of object it is (B or C). Here is some example code below and the question to my problem:
enum ClassType {"B", "C"};
class A {
protected:
m_Type;
public:
ClassType Type() { return m_Type}
...
...
};
class B : public A {
otherMemberFunctions();
}
class C : public A {
otherMemberFunctions();
}
void WhatType(vector<A*>* candidates){
vector<B*> b_candidates(0);
vector<C*> c_candidates(0);
for(int i = 0; i < candidates->size(); i++){
if(candidates->at(i)->Type() == B ){
B* b = (B*) candidates->at(i);
b_candidates(b);
}
//Same idea for Object C
}
}
I would then use WhatType(vector<A*>* candidates) as follows
vector<B*>* b_example
WhatType((vector<A*>*) b_exmaple)
When I have filled the new vector b_candidates in the function WhatType. Will I still have access to the member functions in the B object or will I only have the access to the member functions in the base class A?
I am confused to what happens with the object when I change the type of the object.
Here
WhatType((vector<A*>*) b_exmaple)
and here
B* b = (B*) candidates->at(i);
When you receive a pointer to a polymorphic object you have two types: the "static" type of the object, which, in your case, will be A *, and its "dynamic" or "real" type, that depends on what was actually assigned to it.
Casting your A * to B * forces the compiler to consider that pointer as a pointer to B; this is safe as long as you actually know that that pointer is actually a pointer to B, otherwise the compiler will start writing nonsensical code (invoking B methods on data of another type).
The checks you are trying to implement are a homegrown version of RTTI, which is a mechanism that allows you to know which is the "real type" of a pointer or a reference to a polymorphic class, and to perform that kind of casts safely. Check out typeid and dynamic_cast on your C++ manual for more info about it. (Incidentally, IIRC dynamic_cast is not only for safety in case the dynamic type is wrong, but it may perform also some extra magic on your pointer if you use it in complicated class hierarchies; so, avoid C-style casting for polymorphic classes)
By the way, in general it's considered "code smell" to have to manually check the "real type" of the pointer in order to cast it and use its methods: the OOP ideal would be being able to do the work only though virtual methods available in the base class.
Big warning: RTTI works only on polymorphic classes, i.e. classes that have at least one virtual method. On the other hand, if you are building a class hierarchy where objects are being passed around as pointers to the base class you'll almost surely want to have a virtual destructor, so that's no big deal.
Since you cast to B*, you will have access to B's members.
The actual type of the objects does not change, of course, but if you only have a pointer (or reference) to the base class you can not access fields specific to the sub-classes.
What you can do to access sub-class fields is to use dynamic_cast to cast it to the sub-class:
A *a = new B; // We cant reach the members of class B in a
B *b = dynamic_cast<B *>(a); // But now we have a proper pointer to B
Ok, so if you had an object of type B instantiated on the heap and held by a pointer of type A. you can only see type A's member functions, to access type B's member functions you have to static_cast<B*> which is what the ... "(B*)" ... is doing.
dynamic cast is better as it will return a null if the conversion is not possible. but of course it happens a run-time so there's a penalty.
As B and C are À derived, a vector<B *> and vector<C *> contains A base class objects. If you ensure to set your A::m_Type attribute in your constructor, you will no have problems:
enum ClassType {'B', 'C'}; // see I modified your definition
class A {
protected:
ClassType m_Type;
public:
ClassType Type() { return m_Type};
...
...
};
class B : public A {
public:
B() : m_Type('B') {}
....
};
Using this, you will check without problems your B and Cobjects. After that, as you are casting base objects to derived ones, you will have fully access to their public methods and attributes.