Get address of base object from derived object - c++

I'm getting a very confusing error in my program. I think I may have two different objects of the same class where I thought I had the same object. It is confusing because I am dealing with a very large framework where it is not simple to obtain a pointer to the object I need.
My question is, if I have a class Derived which in inherits from Base, and I have a pointer to a Derived object, how can I get the address of the Base object from the derived object? I am working with the source code of the Base Class and am printing out the address of "this" in Base. In another part of my code a retrieve a pointer to a Derived. I need to be able to print the address of the Base object via my Derived object to determine whether I have a pointer to the particular Derived object I need.
I may have a great misunderstanding of how the addresses work in C++ in inheritance. Perhaps their is only one object, not a base object linked to a derived object?
Thank you very much
Edit:
The reason I want to do this is purely for debugging. The problem is that the code base I'm using does not contain many interfaces or protected members, so I am having to edit the source code to access a certain piece of information. However, my program crashes when I call a method I added to the Base class using a specific Derived pointer. I need to be able to print the address of the base object in this case so that I can determine whether this is the correct object or whether I am getting this error because I actually have a pointer to the wrong object. I realize I can add code to the derived class to cause it to print its address, but I was just wondering if it was possible to get the address without editing the source code any more. Thanks

Going from a pointer to derived class to a pointer to a base class is easy:
Derived * derived_ptr = < some pointer >;
Base * base_ptr = derived_ptr;
If you want to be pedantic, you can use static_cast on the right hand side of the assignment:
Base * base_ptr = static_cast<Base*>(derived_ptr);
Going from a pointer to a base class to a pointer to a derived class uses dynamic_cast:
Derived * derived_ptr = dynamic_cast<Derived*>(base_ptr);
However, this won't always work. You need to have run-time typeid enabled and the base class needs to have at least one virtual method.
Before you go doing this, why do you need to go from a base pointer to a derived pointer? That is a clue that you may need to rethink your design.

There is only one object, it is composed of a Base and a Derived- that is, the Base is put into memory right next to the Derived, in most implementations. That means that the Base* is not the same as Derived* in the general case, but they will be very close.
Now, you can trivially obtain the Base* from the Derived*, the cast is implicit, but you can also make it explicit:
Derived* dptr = ...;
Base* ptr = dptr;
However, there is nothing stopping a single derived object from containing multiple Base objects. Usually this is not the case, but it can happen. That means that you cannot compare Base pointers and expect to know if you are dealing with the same object, only the same Base subobject.

In the simple case of single inheritance, with most compilers:
If you've got a pointer to the derived class, then that's the same as the pointer to the base class. Both pointers have the same value and point to the same memory address.
In memory, if you create an instance of a derived class, it will be laid out as the members of the base object, followed by the members of the derived object. The base class members form part of the derived object.
class Base
{
int b;
};
class Derived : public Base
{
int d;
};
In memory, say the Derived pointer is 0400. Then:
0400 byte 1 of b
0401 byte 2 of b
0402 byte 3 of b
0403 byte 4 of b
0404 byte 1 of d
0405 byte 2 of d
0406 byte 3 of d
0407 byte 4 of d
The derived object consists of the base members and derived's own members, and the address of both of these starts at 0400.
It just so happens, that at 0400, the base object part of derived is located. So, base and derived have the same address.

Related

C++ derived-class members after downcasting

I recently learned about upcasting and downcasting in C++. However I came up with a few questions during reading about downcasting. Say I have two classes
class Base {
public:
virtual void foo() {}
};
class Derived : public Base {
public:
Derived(int i) {
mem = i;
}
int mem;
};
My questions are the followings:
If I create an object Derived d(1), upcast to Base class, and then downcast it back to Derived class, is 'mem==1' preserved? Do I still have access to it? Assume pointer or reference is used so object slicing doesn't happen and dynamic_cast is used for downcasting.
When downcasting from Base class to Derived class, there will an additional member variable 'mem'. Is memory allocated for 'mem' during run-time (using dynamic_cast)? To what value will it be initialized to?
After some simple experiments, 1 seems to be true.
However for 2 it seems I can't start from a Base class pointer and dynamic_cast it into Derived class pointer as dynamic_cast returns null.
I read from another post saying "But the basic point of dynamic_cast is that it first checks that the pointee object is really of the derived type, and then returns a pointer to it, or returns a null pointer if the pointee object isn't actually of (or derived from) the requested target type."
Is this saying we can't actually start from the Base class and simply downcast it into Derived class, but rather the whole point of dynamic_cast is to "cast back" something that has been upcasted?
It depends; if you cast a Derived object to Base, the result is a new object created by omitting the fields that are not in the Base. However, if you cast a pointer to Derived (i.e. Derived*), the result is a pointer which points to the same object but whose type is Base*.
It depends; if you cast a Base object, you get a compile error unless you overload the typecast operator for doing such an operation (you have correctly observed that the values of the fields would otherwise be undefined). However, if you cast a Base* (a pointer) to Derived* (using dynamic_cast<Derived*>(p)), the result depends on the object the pointer points to. If it points to an instance of the Derived class (or its subclass), the result is a Derived* pointer to that object; otherwise, you get a nullptr pointer of type Derived*.

How to find out what type of object a pointer points to in C++?

Let's say I have class SuperClass { public: int a; } and class SubClass : SuperClass { public: int b; } and I took a pointer to an instance of the SubClass SubClass *subPointer and addressed that pointer to a SuperClass pointer SuperClass *superPointer = subPointer. Now of course I can always cast the superPointer object to a pointer of SubClass because the only thing it stores is an adress. But how would I know if the object superPointer is pointing to an instance of SubClass or is just a SuperClass pointer?
You usually don't want to use typeid for this.
You usually want to use dynamic_cast instead:
if (SubClass *p = dynamic_cast<SubClass *>(SuperClassPtr))
// If we get here (the `if` succeeds) it was pointing to an object of
// the derived class and `p` is now pointing at that derived object.
A couple of notes though. First of all, you need at least one virtual function in the base class for this to work (but if it doesn't have a virtual function, why are you inheriting from it?)
Second, wanting this very often tends to indicate design problems with the code. In most cases, you want to define a virtual function in the base class, which you (if necessary) override in the derived class to do whatever's needed so you can just use a pointer to the base class throughout.
Finally, as it stands right now, most of the conversions will fail -- you've used the default (private) inheritance, which prevents the implicit conversion from derived * to base * that you'd normally expect to see happen (you probably want class SubClass : public SuperClass).
Use RTTI machanism. Like:
if(typeid(*superPointer) == typeid(SuperClass)) superPointer->dosomething();
if(typeid(*superPointer) == typeid(SubClass)) superPointer->dosomethingelse();

C++ passing object by reference and casting

I have an object of a base class which is actually pointing to a derived class like this
Base *b = new Derived()
What I want to know, is it possible to pass the base class pointer by reference to some function which can cast the object back to Derived class. Something like this
Dummy_cast_fn(&b) // casts b to derived class
After calling Dummy_cast_fn, b should have a full copy of Derived class (no slicing).
Edit
I dont understand the part that there is no slicing since pointers are used. My problem is Derived class is returned from a function call to a shared library and I do not have access to .h file for the Derived. Only information I have is that Derived is based on Base class. I have access to Base.h so I can instantiate an object of Base but problem comes when I try to access the functions which are defined in Derived but not in Base. So I was wondering if I can typecast the Base to Derived type, then I will be able to access the function defined in Derived and not in Base.
As long as b is a pointer or reference to a Derived, you can always:
Down cast it to a Derived.
Treat it as a Base as long as you're using b.
Namely, what determines what you can do with b is its static type, in this case Base. However, since it actually points on a Derived, you can always downcast it. Yet, to use it as a Derived you must have a variable whose type is Derived as well.
So, if the purpose of Dummy_cast_fn is just to fix something in b - it's useless. If an object is sliced, nothing can fix it. But in your case, there's no slicing, since you're using pointers.
Edit according to the question's edit:
First, you're Derived object is not sliced. Let's get that off the table. You have a pointer to a complete Derived (assuming that's what you've been passed), but you only have access to its Base part when using the Base pointer. Now, you say you don't have the definition of Derived. This means you won't be able to downcast to that type, because the compiler doesn't know how it's defined. No casting will work here. There's no legal C++ way you can call that sum function if you don't have Derived's definition.
I do wonder why the author of Derived provided you its documentation without providing its definition. With this kind of polymorphism, the provider usually lets the user have some "interface", leaving the actual type as an internal implementation detail. If you can't use Derived because you don't have its definition, there's no point in letting you have its documentation.
You cannot change a Base* into a Derived*, but you can get a Derived* pointing to the object that a Base* is pointing to, using dynamic_cast:
Derived* d = dynamic_cast<Derived*>(b);
if (d) {
// cast was succesful
} else {
// cast failed,
// e.g. because b* does not point to a Derived* but some other derived type
}
You can't change the type of your Base* b, you can however create a new pointer
Derived* p = static_cast<Derived*>(b);
and use that. Once b is declared as Base* you can't modify its type. You can also use dynamic_cast also although this is slower and may not strictly be necessary (although I cannot say for certain - that depends on your requirements). And if you are correctly using virtual functions you may not even need to do any casting at all - that is one of the purposes of polymorphism

virtual derived class of a non-virtual base class

I have a virtual class that has been derived from a non virtual class. But when I c-style cast the derived class to base class, the class is corrupted. I am looking at the member variables using the debugger and the member variables are all corrupted when I do that cast. I see there is a 4 byte discrepency when I do that cast(may be the virtual pointer) using debugger.
For Ex:
class A//non-virtual class
{
~A();
int fd;
};
class B:public A
{
virtual ~B();
};
Now say the address of obj of type B is: 0x9354ed0.
Now when I cast it (A*)(0x9354ed0) debugger moves the bytes by 4 bytes. So starting address of the casted obj is 0x935ed4
Is it wrong to cast a derived virtual class to base non-virtual class? What is the reason for 4 byte discrepancy?
And what is the right way to cast it? Thanks for any input or explanation.
Here is what you described.
class A
{
public:
~A();
// other stuff
};
class B: public A
{
public:
virtual ~B();
// other stuff
};
It is perfectly legal to derive a class from a non-virtual base class, and to make the derived class virtual. The 4 bytes offset (can be 8) corresponds to a hidden member variable of type pointer that points to the virtual functions table of the class.
When you cast pointers across the hierarchy, actual numerical pointer values might change. There's nothing wrong with the fact that it changes. There's noting wrong with such a cast. How the numerical pointer values change depend on the physical layout of the class. It is an implementation detail.
In your example, the 4 byte change in pointer value might easily be caused by the presence of virtual table pointer in the derived class.
The change in pointer value will not corrupt any member variables. The example in your original post does not show any "corrupted member variables" and in general your claim about some member variables getting "corrupted" doesn't make much sense. Please, when you make such claims, illustrate them with an example, so that people can understand what on Earth your are talking about.
Update:
The fact that base class subobjects might have non-zero offsets inside the derived classes immediately mean that in order to perform a proper cast from derived pointer type to base pointer type the compiler must know the source type and the destination type and the relationship between them. For example, if you do this
B* pb = /* whatever */;
A* pa = pb;
the compiler will know how to properly offset pointer pa from pointer pb. But of you do this
A* pa = (void *) pb;
the compiler will forget about the relationship between A and B, fail to perform the proper offset and produce the invalid value of pa. The effect would be the same as in
A* pa = reinterpret_cast<A*>(pb);
If you do it this way, the result will be meaningless. So, just don't do it.
Of course, if you manually inspect the numerical value of pb and find out that it is, say, 0x12345678, and then do
A* pa = (A*) 0x12345678;
you will also get completely meaningless results, because the computer has no way to know that it has to perform the proper offset of the pointer.
This will produce an illusion of members of A getting "corrupted", while in fact the only thing that is corrupted is your pointer. And you are the one who corrupted it.
If that is the shell of the code you are using then you aren't deriving the class B from class A. If you wanted to do that you would need to do this:
class A
{
public:
virtual ~A();
// other stuff
};
class B: public A
{
public:
virtual ~B();
// other stuff
};
I really don't think you can cast the way that you were hoping to in your question. If you are using virtual functions and derived classes then they need to be declared virtual upon first usage. Plus, I'm not 100% sure but if you have any virtual destructors you need to have all virtual destructors in your heirarchy.
Hope that helps,
nmr
The missing four bytes are, indeed, the vptr of the object; since class A has no vtable, a pointer to A has no vptr.
While it is actually legal deriving a class with virtual methods from another class with none, it is not a good idea. Inheriting from a class with no virtual methods is usually unsound, since that class is not intended to be used polymorphically, which is the main reason behind inheritance. All kinds of bad things can happen if you do it. If you try to use derived class objects through base class pointers, you may well run into the dreaded undefined behaviour (most likely a crash). For instance, trying to delete a base class pointer pointing to a derived class object.
Its legal to point derived class object using base class pointer
that's called run time polymorphism i.e. based on dynamic type of object functions are dispatched.
When you define a class with virtual function,a table comprising of virtual function address is formed called virtual function table.
When you declare an object of a class with virtual function , a virtual pointer pointing to corresponding virtual function table is insert into it.

Declaring pointer to base and derived classes

I just found that I am confused about one basic question in C++
class Base {
};
class Derived : public Base {
}
Base *ptr = new Derived();
What does it mean? ptr is pointing to a Base class or Derived class? At this line, how many memory is allocated for ptr? based on the size of Derived or Base?
What's the difference between this and follows:
Base *ptr = new Base();
Derived *ptr = new Derived();
Is there any case like this?
Derived *ptr = new Base();
Thanks!
For Base *ptr = new Derived(); memory is allocated according to Derived class. ptr points to the object but the compiler is instructed to only "grant access" (visibility) to the members of the object that are declared in the Base class.
Of course the memory associated with the pointer ptr is the same i.e. independent of the object it is instructed to point to. Usually, the size of a "pointer object" is constant on a CPU architecture e.g. 32bits / 64bits (or smaller on embedded devices for example).
For Derived *ptr = new Base();: no, this is invalid.
Class Derived isn't just a class Base but is defined as deriving from Base: hence, a pointer instance to a Derived object instance can't be just assigned to an object instance of class Base.
You might consider perusing the very good Wikipedia contributions on Polymorphism and Inheritance.
Polymorphism
ptr is a pointer; it has the same size regardless of what it points to.
On a 32-bit system, 4 bytes of stack space are allocated for ptr. On a 64-bit system, it would be 8 bytes. (Assuming that the compiler doesn't decide to leave it in a register and not allocate any stack space at all).
The reason you can let a pointer to a Base point to a Derived is one of the basic principles of OOP - polymorphism. A Derived is a Base. You can stick it in anywhere a Base could be used.
Your last line (Derived *ptr = new Base();) is invalid because a Base is not a Derived.
To understand the type system of C++, its important to understand the difference between static types and dynamic types. In your example, you defined the types Base and Derived and the variable ptr which has a static type of Base *.
Now when you call new Derived(), you get back a pointer with a static and dynamic type of Derived *. Since Derived is a subtype of Base this can be implicitly converted to a static type of Base * and assigned to ptr as the static types now match. The dynamic type remains Derived * however, which is very important if you call any virtual function of Base via ptr, as calling virtual functions is always based on the dynamic type of the object, not the static type.
Your question hits on one of the most important parts of object-oriented programming: polymorphism.
Derived is a subtype of Base. That means that everything that Base can do, Derived can also do. Often, Derived is more specific than Base: it works on a subset of what Base does, but it does that subset much better than what Base does.
Think about an example.
Think about writing a graphics program. You might have a class, ClosedShape, and a method inside it, fill(). It's possible to create a very generic method that can fill any closed shape... but usually, that method will take memory, and it might be slow.
You might have another class, Square. Now, filling squares is very easy and very fast: it's two nested for loops. Since Square does everything that ClosedShape does, it can inherit from ClosedShape.
Why is polymorphism important? Think about many different kinds of ClosedShape: triangles, hexagons, and so forth. If you want to fill all of them, just do:
for (i=0; i<num; i++) {
cs[i].fill();
}
They all will use their own version of fill()!
For Base *ptr = new Derived(); memory is allocated according to Derived class. ptr points to the object but the compiler is instructed to only "grant access" (visibility) to the members of the object that are declared in the Base class.
Of course the memory associated with the pointer ptr is the same i.e. independent of the object it is instructed to point to. Usually, the size of a "pointer object" is constant on a CPU architecture e.g. 32bits / 64bits (or smaller on embedded devices for example).
For Derived *ptr = new Base();: no, this is invalid.
Class Derived isn't just a class Base but is defined as deriving from Base: hence, a pointer instance to a Derived object instance can't be just assigned to an object instance of class Base.
A Derived object is appended to the end of the Base object, so the prefix [in bits] of Derived is actually a Base, so there is no problems to assign a Derived* object to a Base* variable. It is perfectly safe to access any of Base's fields/methods of the Derived object.
However - the oposite is not true. If you assign the address of the Base* to a Derived* variable and then access one of the fields of Derived [which is not in Base] you will get out of the allocated space.
Typing reasoning:
Also note that a value can be assigned to a variable only if it is of the correct type without casting [c++ is static typing langauge]. Since Derived is a Base, Derived* is a Base* - so this is not conflicting, but the other way around is not true.
I highly recommend to read the comment to understand the logic as well