reinterpret_cast and dynamic cast questions - c++

I've read about reinterpret and dynamic cast, but I saw some examples which I have questions about.
reinterpret_cast:
#include <iostream>
using namespace std;
class A
{
public:
void a() {
cout << "a";
}
};
class B: private A
{
public:
void a() {
cout << "b";
}
};
int main()
{
A *a = new A();
B *b = reinterpret_cast<B*>(a);
B *b2 = new B();
a = reinterpret_cast<A*>(b2);
b->a();
a->a();
return 0;
}
Would print ba.
My explanation was that reinterpret_cast change the bit pattern, and both types has a funtion called a() so that was the result.
Then I saw this:
using namespace std;
class B;
class A
{
private:
int j = 4;
public:
A() {}
A(const B &b) {}
void a() {
cout << j << endl;
}
};
class B
{
private:
int i = 5;
public:
B() {};
B(const A &a) {}
void a() {
cout << i << endl;
}
};
int main()
{
A *a = new A();
B *b = reinterpret_cast<B*>(a);
B *b2 = new B();
a = reinterpret_cast<A*>(b2);
b->a();
a->a();
return 0;
}
and that printed 45. I guess it has something with inheritance but I don't know how or why.
About dynamic cast:
#include <iostream>
using namespace std;
class A {
public:
virtual ~A(){}
};
class B {
public:
void a() {
cout << "B" << endl;
}
virtual ~B() {}
};
int main()
{
A *a = new A();
dynamic_cast<B*>(a)->a();
return 0;
}
That would print "B".
But if I would write:
virtual void a() {
cout << "B" << endl;
}
I would get segmentation fault.
Why I got the result I got in both examples?
Thanks for all your help!

In the first case, you're basically lying to the compiler and telling it to pretend a pointer to an A is a pointer to a B without doing necessary conversions. However, it doesn't matter because the function isn't virtual, so it just calls the function based on the pointer type.
In the second case, the dynamic cast fails because the two types are unrelated. but you still invoke B::a, just on no object. That causes no problem because no attempt to access the object takes place.
In the third case, the dynamic cast fails again. But since the function is virtual, executing it requires accessing the object to determine its fully-derived type. Since there is no object (no instead of a B exists), that fails.

The object pointed to has a compile-time type and a run-time type. You need to understand how each of those affects the action taken.
When you do a reinterpret_cast you have changed the compile-time type but have not changed the run-time type.
When you call a non virtual function, which class you get that function from depends only on the compile-time type not the run-time type. That function then assumes the run-time type is either the same as the compile-time type or derived from it. That assumption is false in your first example, which makes the behavior undefined in theory. But in practice, the function doesn't actually use the object, so the object being the wrong type has no consequence.
In your second example, you still call the function in the class of your compile-time type. Your testing hides that fact, so you may be confused about that. But the object is of the run-time type so its data is as initialized in the run-time type. That data is accessed by position, not by name. So the use of i gets the actual value of j (through very undefined behavior) because it has the same position. I expect that caused you to be confused over which function was called. You could make that example easier to understand if you changed:
cout << i << endl;
to
cout << "i == " << i << endl;
In your third example, the dynamic_cast still unconditionally changes the compile-time type to the requested type. But in case the requested type cannot be correctly reached from the run-time type of the actual object (as is true in your example of unrelated classes) the pointer itself is null. So when you then call a function that doesn't actually use the object, the result is technically undefined but in practice executes as the compile-time type. But when you call a virtual function, the call itself uses the object and since the object pointer is null, that will seg fault.

Related

Reinterpret cast to different type C++

While reading about Reinterpret cast, I was checking the following code.
class Type1 {
public:
Type1() {
a = "Class Type 1";
}
void get1()
{
std::cout << a;
}
private:
std::string a;
};
class Type2 {
public:
Type2() {
b = "class Type 2";
}
void get2()
{
std::cout << b;
}
private:
std::string b;
};
int main()
{
Type1* type1 = new Type1();
//converting Pointer
Type2* type2 = reinterpret_cast<Type2*>(type1);
// accessing the function of class A
type2->get2();
}
After running the following code it prints in console "Class Type 1"
Now type1 is pointer of type Type1 and i cast it to Type2 and store in type2.
Now when i call type2->get2(); Is it printing the data member a of instantiated Type1 or compiler is dynamically changing function ?
Similarly in Following Code.
#include <iostream>
using namespace std;
class A {
public:
void fun_a()
{
cout << " In class A\n";
}
};
class B {
public:
void fun_b()
{
cout << " In class B\n";
}
};
int main()
{
// creating object of class B
B* x = new B();
// converting the pointer to object
// referenced of class B to class A
A* new_a = reinterpret_cast<A*>(x);
// accessing the function of class A
new_a->fun_a();
return 0;
}
How "In class A" is getting printed? since I instantiated Class B ?
What you are doing is undefined behavior. There is no correct answer to this.
It is illegal in C++ to use a pointer/reference resulting from a reinterpret_cast between two types of an unrelated hierarchy -- and so any code that generates from such cannot be reasoned about.
With undefined behavior, the compiler is free to do what it wishes with the invalid code. What you are experiencing may change between different compilers, optimization levels, and target architecture/system.
You used conversion reinterpret_cast in your code
This conversion only tells the compiler to consider pointing to a different type, regardless of the type.
reinterpret_cast is the most illegal cast in C ++ that pays no attention to the destination and source data arrangement. And it just converts the value from one type to another.

Why does the base class pointer point to the pure virtual method in the base class instead of the overidden method in the derived class?

#include <iostream>
class A
{
public:
virtual ~A() = default;
virtual void foo(void) = 0;
};
class B : public A
{
private:
int x;
public:
B(int a) : x(a) {}
void foo(void) { std::cout << "B: " << x << "\n"; }
};
class Foo
{
private:
A* a_ptr;
public:
Foo (B& x) { a_ptr = &x; }
A* get_ptr(void) { return a_ptr; }
void dummy(void) { std::cout << "Foo: "; std::cout << a_ptr << "\t "<< typeid(*a_ptr).name() << "\n"; a_ptr->foo(); std::cout << "\n"; }
};
int main(void)
{
B b(10);
Foo f(b);
f.dummy();
return 0;
}
If the constructor of Foo takes a reference to an object of B, then this program executes the way I expect it to, i.e. a_ptr->foo() calls B::foo().
However, if the constructor is changed to accept the parameter by value, then a_ptr->foo() resolves to A::foo(), and results in a pure virtual method called exception
Sample output (Passed by reference:):
Foo: 0x7fffe90a24e0 1B
B: 10
Sample output (Passed by value):
Foo: 0x7fffc6bbab20 1A
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
I've a vague hunch as to why this might be happening, and I'm looking for some literature or reference which might prove or disprove my hypothesis: When passed by reference, the base class pointer a_ptr points to an entity whose lifetime exceeds past the call to a_ptr->foo().
However, when passed by value, a_ptr points to a temporary which is lost when the constructor exits.
I suppose this has something to do with the VTABLE of A, but I can't quite put my finger on it.
Yes, your suspicion is correct.
When the B object is passed by value into the Foo constructor, it becomes a local variable of the constructor. The constructor is saving a pointer to that local object, which goes out of scope when the constructor exits.
So, the call to a_ptr->foo() in Foo::dummy() is actually undefined behavior since a_ptr doesn't even point at a valid object to begin with. But, it doesn't really crash since A::foo() doesn't use its this pointer for anything. It just points to a compiler-defined function that throws the pure virtual method called error, which you don't catch, so your program terminates.
You assigned temporary object B by reference to a_ptr which is of type A*. On constructor exit this temporary object has beed destroyed. As VTABLE has been destroyed too, called A::foo, which is pure virtual. So you got it.

c++: Is a multiple inheritance from template class and general class valid?

I'm trying to figure out why b->boo() actually calls a.far().
is the multiple inheritance from template class and general class forbidden? why does the inherit order matter?
The code is here:
#include <iostream>
template <int somecount>
class inner_parent_class
{
public:
int array[somecount];
virtual void far() = 0;
};
class any_class
{
public:
virtual void boo() = 0;
};
template <int somecount>
class child_class_bad : public inner_parent_class<somecount>, public any_class
{
public:
virtual void boo() override
{
std::cout << "call me" << std::endl;
}
virtual void far() override
{
std::cout << "do not call me" << std::endl;
}
};
template <int somecount>
class child_class_good : public any_class, public inner_parent_class<somecount>
{
public:
virtual void boo() override
{
std::cout << "call me" << std::endl;
}
virtual void far() override
{
std::cout << "do not call me" << std::endl;
}
};
int main()
{
{
child_class_good<32> a;
any_class* b;
auto c = dynamic_cast<void*>(&a);
b = reinterpret_cast<any_class*>(c);
b->boo();
}
{
child_class_bad<32> a;
any_class* b;
auto c = dynamic_cast<void*>(&a);
b = reinterpret_cast<any_class*>(c);
b->boo();
}
return 0;
}
# GCC 9.3.0
# VS 2019 16.5.3
I suppose that both child classes (child_class_good and child_class_bad) are different classes even though their class names are the same, because they are template classes and constructed separately at compiled time. Nevertheless, each class might have its own v-table, so I think calling boo() as their common parent class any_class should correctly work.
reinterpret_cast cannot be used to do what you're trying to do. A reinterpret_cast from a void* to a T* only produces a pointer to a valid T* if the void* pointer it was given was a pointer to an object of type T.
Doing a dynamic_cast<void*>(p) returns a void* which points to the most-derived object pointed to by p. Since your &a is in fact the most-derived object that it points to, it simply converts the pointer to a void*.
Then you perform reinterpret_cast<any_class*> on that void*. The void* points to an object of type child_class_good<32> or child_class_bad<32>. Your cast is saying that the pointer actually points to an any_class. This is incorrect (neither type is standard layout, so the layout of the base classes is not defined), and thus attempting to use the results will yield undefined behavior.
The case that you identify as good is just as invalid as bad; it merely happens to work.
It is not clear why you're trying to do whatever it is you're trying to do, but there's no valid way to take a void* pointing to the most-derived object of an unknown type and casting it to anything useful. In order to use a void*, you have to know the exact type that was used to produce that void*.

Strange behavior of 'this' with inheritance

I'm having trouble understanding the value of this in the following example:
struct A {
int i;
void bar() {
cout << this << endl;
}
};
struct B : public A {
virtual void foo() = 0;
};
struct C : public B {
void foo() {
printf("hello world!\n");
}
};
int main (int argc, const char* argv[]) {
C* c = new C;
cout << c << endl;
c->bar();
return 0;
}
Both times I print the pointer to the console, I get different values. I would expect it to be the same, as they refer to the same instance both times?!
If I remove either the virtual function or the int i in A it goes away. Why?
But it refers to differnt things.
void bar() {
cout << this << endl;
}
Here this has a type A*. It points to the part of the object that is A.
out << c << endl;
Here c is a C* and points to the part of the object that is C.
If the A object lines up exactly with the C object the pointers are the same. If they do not (like when C contains other members (hidden pointer to the vtable) and thus the 'A' part is offset from the start of the larger object) then the pointers are not necessarily the same.
It is a compiler optimization. The A struct doesn't have any virtual methods so it doesn't need a v-table. No point storing a pointer to it in an object of type A. Which makes the object layout different between objects of type A and C since C does need a v-table. The compiler makes up the difference by incrementing this before calling a method of A.
Add an arbitrary virtual method to A to make the pointers match.

dynamic_cast of "this" inside constructor

This question is very similar to this one Why can't I dynamic_cast "sideways" during multiple inheritence?, except that the cast does work - just not inside in the constructor.
Header:
class A
{
public:
virtual ~A() {}
void printA();
};
class B
{
public:
B();
virtual ~B() {}
void printB();
private:
std::string message_;
};
class C : public A, public B
{
public:
C() {}
virtual ~C() {}
};
Source:
void A::printA() { cout << "A" << endl; }
B::B()
{
A* a = dynamic_cast< A* >( this );
if ( a ) {
message_ = std::string( "A and B" );
} else {
message_ = std::string( "B" );
}
}
void B::printB() { cout << message_.c_str() << endl; }
Main:
int main( int argc, char* argv[] )
{
cout << "Printing C..." << endl;
C c;
c.printA();
c.printB();
cout << "Checking again..." << endl;
cout << !!dynamic_cast< A* >( &c ) << endl;
return EXIT_SUCCESS;
}
Result:
Printing C...
A
B
Checking again...
1
So, the dynamic_cast does work for multiple inheritance (no surprises there!), but why not when called at runtime for the 'this' pointer inside B::B()? I thought that the object was fully formed once inside the body of the constructor i.e. all the memory was allocated for the component objects, they haven't been initialised yet. I appreciate that this depends on the superclass constructor order, but in this example A is called before B.
I am obviously not understanding what exactly is happening under the hood, can someone please enlighten me?
Thanks,
Cam Bamber.
Basically the standard says it will not work (dynamic_cast) during construction of an object.
<quote>
Edit: Added based on VJo comment below.
Note: The cast from a 'B' to an 'A' using dynamic cast should work because we are casting an object of type 'C'. If we added the following code to main:
B bObj;
B& bRef = c;
B* bPtr = &c;
std::cout << !!dynamic_cast<A*>(&bObj) << std::endl;
std::cout << !!dynamic_cast<A*>(&bRef) << std::endl;
std::cout << !!dynamic_cast<A*>( bPtr) << std::endl;
The extra output would be:
0 // Can not convert a B to an A
1 // Can convert this B to an A because it is really a C.
1 // This is what we are reeling doing in B::B() that fails
// It is not the dynamic_cast<> that fails but the conversion of this from C* to B*
// That is causing UB
It fails in the constructor because the object is not fully formed. Using this we are trying to convert a C pointer into a B pointer before the C constructor has started (the code defined by the user). Thus the use of this in B::B() as a pointer to a C object fails thus when the dynamic_cast<> is called on this it fails to do what you want it to because of UB.
12.7 Construction and destruction [class.cdtor]
Paragraph 3
To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference) to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior. To form a pointer to (or access the value of) a direct non-static member of an object obj, the construction of obj shall have started and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing the member value) results in undefined behavior.
[ Example:
struct A { };
struct B : virtual A { };
struct C : B { };
struct D : virtual A { D(A*); };
struct X { X(A*); };
struct E : C, D, X
{
E() : D(this), // undefined: upcast from E* to A*
// might use path E* → D* → A*
// but D is not constructed
// D((C*)this),
// defined:
// E* → C* defined because E() has started
// and C* → A* defined because
// C fully constructed
X(this) { // defined: upon construction of X,
// C/B/D/A sublattice is fully constructed
}
};
— end example ]
</quote>
Each base class constructor is executed before the derived class constructor, and during the B constructor, the dynamic type of the object is B; it does not become a C until you enter the C constructor. So you cannot do anything that requires a dynamic type of C: you can't cross-cast to any of Cs other base classes, and if you called a virtual function, then you would not get any overrides provided by C.
Under the hood, the dynamic type is (in most implementations at least) determined by a pointer in the object (known as the "vptr"), which points to some static data specifying properties of the class, including a table of virtual functions (known as the "vtable") and the information needed for dynamic_cast and typeid. Before each constructor, this is updated to point to the information for the class currently under construction.
During the construction of A then the dynamic type is A regardless. This is because you would start calling member functions of derived classes and accessing derived member variables before it's been constructed, which would be UB and very bad.
Since B doesn't inherit from A (B is parent-most class), the dynamic type of B during its constructor is B. Only when both the A and B parents are constructed can the child C be constructed, allowing for sideways dynamic_casting.
It doesn't work inside B, because B doesn't inherit from A