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.
Related
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*.
I've a code as follows -
#include <iostream>
#include <string>
class A{
int a;
public: virtual void sayHello(){ std::cout << "Hello\n"; }
};
class B : private A{
std::string name;
public:
B(std::string _n): name(_n){}
void sayName(){std::cout << name << "says hello\n";}
void sayHello(){sayName();}
};
int main() {
A *ptr = new B("c++");
ptr->sayHello();
return 0;
}
which produces the following compiler output -
Error:
prog.cpp: In function 'int main()':
prog.cpp:20:22: error: 'A' is an inaccessible base of 'B'
A *ptr = new B("c++");
^
As previously answered - here, here & here, I know how to solve this issue. By using public inheritence instead of private or protected.
But if I really really want to hide some interface behind the base class, isn't there some other way to do this? Or is it impossible to do so according to c++ lang specification.
If you want polymorphic pointer conversion to work outside the class, then the inheritance must be public. There is no way to work around that.
You could add a member function that does the polymorphic pointer conversion within the class:
class B : private A{
// ...
public:
A* getA() {
return this;
}
};
Which allows you to do this, while still allowing private inheritance:
B* b_ptr = new B("c++");
A* ptr = b_ptr->getA();
// ptr = b_ptr; // only allowed in member functions
I haven't encountered a real world design where this trick would be useful, but suit yourself.
PS. Remember that you should destroy objects that you create. Also do realize that delete ptr has undefined behaviour, unless ~A is virtual.
Even though I find it quite strange to hide the base class and want to cast B to A, you can use for that the operator A*().
It follows a minimal, working example:
#include <iostream>
#include <string>
class A{
int a;
public:
virtual void sayHello(){ std::cout << "Hello\n"; }
};
class B : private A{
std::string name;
public:
B(std::string _n): name(_n){}
operator A*() { return this; }
void sayName(){std::cout << name << "says hello\n";}
void sayHello(){sayName();}
};
Now you can use it as:
int main() {
A *ptr = *(new B("c++"));
ptr->sayHello();
return 0;
}
Or even better:
int main() {
B b{"c++"};
A *ptr = b;
ptr->sayHello();
return 0;
}
Adding the cast to A& is as easy as adding the member method operator A&() defined as return *this;.
There is an unsightly way around this: C style casts. C style casts can cast to inaccessible base classes. This is the one and only case where C style casts can do something that C++ casts can't. From cppreference, when a C style cast (T) foo attempts to perform static_cast<T>(foo), it can do slightly more than just a static_cast:
[P]ointer or reference to a derived class is additionally allowed to be cast to pointer or reference to unambiguous base class (and vice versa) even if the base class is inaccessible (that is, this cast ignores the private inheritance specifier).
Emphasis added
Thus, you can do this:
int main() {
A *ptr = (A *) new B("c++");
ptr->sayHello();
return 0;
}
This is ugly, and it comes with all the disadvantages of casting and especially of C style casts. But it does work, and it is allowed.
Live on Wandbox
When you want to hide that A is a base of B this is valid.
But you assignment
A *ptr = new B("c++");
breaks this hiding, because you use an A*. So c++ generates an error because the dependency is hidden. You can do
B *ptr = new B("c++");
though.
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.
class A
{
public:
virtual void func() {
cout<<" func():: in class A"<< endl;
}
void func1(){
cout<<"func1():: in class A";
}
};
class B: public A {
public:
void func() {
cout<<" func():: in class B"<< endl;
}
void func1(){
cout<<"func1():: in class B";
}
};
int main()
{
A a;
A* pa = &a;
B* pb = dynamic_cast<B*>(pa);
pb->func1();
return 0;
}
Though pb is pointing to an incomplete type and dynamic_cast will return null.
But why it is not crashing in this scenario?
Since func1 in your B class doesn't access any member variables (or virtual functions) it doesn't use the implicit this pointer and therefore, in this case, does not crash.
Note that this is undefined behaviour so it may crash (or do something unexpected) in a different compiler (or compiler version) so don't depend on this behaviour.
You have a A * that is pointing to an instance of A, not A * that is actually pointing to an instance of B. That is why dynamic_cast returns a null pointer of type B *, it is not related to these being incomplete types or anything (in the linked code, both A and B are complete types), and thus this is defined behaviour for dynamic_cast. However after that a null pointer is accessed; a clever compile can know that dynamic_cast can fail at that point and the pb->func1(); can do anything including not causing a null pointer exception or anything at all, or even calling the pb1->func on something that is not B.
An example with an incomplete type would be:
#include <iostream>
using namespace std;
class A {
public:
virtual void func() {
cout << "func():: in class A" << endl;
}
void func1(){
cout<< "func1():: in class A";
}
};
class B;
int main() {
A a;
A* pa = &a;
B* pb = dynamic_cast<B*>(pa);
return 0;
}
Now if you compile this with G++, you get
y.cc: In function ‘int main()’:
y.cc:20:32: error: cannot dynamic_cast ‘pa’ (of type ‘class A*’) to
type ‘class B*’ (target is not pointer or reference to complete type)
B* pb = dynamic_cast<B*>(pa);
that is all sane C++ compilers will reject such code.
I have a somewhat basic question on inheritance that i can seem to figure out, I've done a search and not found what I was looking for so I thought I'd ask here (not sure if title of what I'm looking for is correct).
To keep things simple I've made a bit of example code to illustrate what I'm not getting.
Basically if I have a parent class A and two child classes B & C,
where A contains common stuff (say an id with get/set),
while B & C have functions that are class specific.
If you declare a class B like: A *bObject = new B();
how do you then access the class specific functionbObj->specific()`?
I've tried virtual but that requires both B & C to have the same function name / prototype declared.
I've also tried declaring the abstract in A, but that requires it to be prototype to be in A.
Where am i going wrong here? any help on this, probably basic issue would be helpful.
#include <iostream>
using namespace std;
// A class dec
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
};
// B class dec - child of A
class B :
public A
{
public:
B(void);
~B(void);
void sayHello();
};
//C class dec - child of A
class C :
public A
{
public:
C(void);
~C(void);
void sayGoodby();
};
//a stuff
A::A(void)
{
}
A::~A(void)
{
}
void A::setId(char id)
{
this->id = id;
}
char A::getId()
{
return this->id;
}
//b stuff
B::B(void)
{
this->setId('b');
}
B::~B(void)
{
}
// c stuff
C::C(void)
{
this->setId('c');
}
C::~C(void)
{
}
void C::sayGoodby()
{
std::cout << "Im Only In C" << std::endl;
}
// main
void main ()
{
A *bobj = new B();
A* cobj = new C();
std::cout << "im class: " << bobj->getId() << endl;
bobj->sayHello(); // A has no member sayHello
std::cout << "im class: " << cobj->getId() << endl;
cobj->sayGoodby(); // A has no member sayGoodby
system("PAUSE");
}
Thank you for your time!
To access methods unique to a derived class, you need to cast the base class pointer to the correct derived class type first (a downcast):
A *bobj = new B();
bobj->sayHello(); // compile error
dynamic_cast<B*>(bobj)->sayHello(); // works
dynamic_cast<C*>(bobj)->sayGoodbye(); // run-time error - probably crashes with a segfault/access violation.
dynamic_cast ensures run-time type safety but adds a small overhead to the cast; for pointer casts, it returns a null pointer if the pointed-to object is not actually a B, and you should check the return value before using it. Alternatively, if you are really sure that the pointer you are casting is pointing to the correct object, you can use static_cast which saves you the cost of the run-time checking, but if the pointer is not pointing to the right object, you get undefined behavior.
A *bobj = new B();
A* cobj = new C();
Here instance of B and C is pointed by pointer of A. Since A have no virtual function for B and C's member function sayHello() and sayGoodbye(), they could not called by bobj->sayHello() and cobj->sayGoodbye(). It is not what polymorphism should be do.
Class A should be:
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
virtual void sayHello(){/* to do */ };
virtual void sayGoodbye(){ /* to do */ };
};
Then the bobj->sayHello(); and cobj->sayGoodbye(); could be called without complaning.
A *bobj = new B();
The static type of bobj is A *. So, at compile time, the compiler looks for the member functions in the class A definition, what ever you tried to access through bobj. Now,
bobj->sayHello();
the compiler will look for the sayHello in class A since the type of bobj is A *. Compiler doesn't care to look into the class B definition to resolve the call. Since the compiler didn't find it sayHello member in A, it is complaining.
However, the dynamic type of bobj is B * and that is a where call is dispatched depending on the dynamic type.
To resolve the issue, you need to virtual functions of the same in class A.
if you really want to call a function like this, you can do like this:
A* bobj = new B();
((B*)bobj)->sayHello();//this can be dangerous if bobj is not an instance of class B
however, the problem here is you do the design wrongly.
basically, if you create an class A, and subclass it to B and C.
And then assign A* bobj = new B(); you are splitting the interfaces and implementations. That means you will use bobj as if it is an instance of class A. and you will not call the functions in B or C. B & C are implementations of interface class A.
it's just like you hire someone to build your house. You give them your blueprint(interfaces) and hire them to build. you can alter the blueprint as you like, they will do whatever in blueprint. but you can't order them directly(just like you can't call the sayHello() directly from bobj).
You can use a down cast via dynamic_cast<>. You can implement a template method in your base class A to facilitate the down cast:
class A
{
public:
A(void);
virtual ~A(void);
char id;
void setId(char id);
char getId();
template <typename CHILD, typename R, typename... ARGS>
R invoke (R (CHILD::*m)(ARGS...), ARGS... args) {
CHILD *child = dynamic_cast<CHILD *>(this);
if (child) return (child->*m)(args...);
std::cout << "down cast error: " << typeid(CHILD).name() << std::endl;
}
};
If that particular instance of A was not the base of CHILD, then dynamic_cast<CHILD *>(this) result in NULL. Note that the virtual destructor in A is required for the dynamic_cast<> to work.
So, you can use it like this:
std::unique_ptr<A> bobj(new B());
std::unique_ptr<A> cobj(new C());
bobj->invoke(&B::sayHello);
bobj->invoke(&C::sayGoodbye);
cobj->invoke(&B::sayHello);
cobj->invoke(&C::sayGoodbye);
Only the first and last invocations are valid. The middle two will cause the "down cast error" message to be printed.