I have a class A and another class that inherits from it, B. I am overriding a function that accepts an object of type A as a parameter, so I have to accept an A. However, I later call functions that only B has, so I want to return false and not proceed if the object passed is not of type B.
What is the best way to find out which type the object passed to my function is?
dynamic_cast should do the trick
TYPE& dynamic_cast<TYPE&> (object);
TYPE* dynamic_cast<TYPE*> (object);
The dynamic_cast keyword casts a datum from one pointer or reference type to another, performing a runtime check to ensure the validity of the cast.
If you attempt to cast to pointer to a type that is not a type of actual object, the result of the cast will be NULL. If you attempt to cast to reference to a type that is not a type of actual object, the cast will throw a bad_cast exception.
Make sure there is at least one virtual function in Base class to make dynamic_cast work.
Wikipedia topic Run-time type information
RTTI is available only for classes that are polymorphic, which means
they have at least one virtual method. In practice, this is not a
limitation because base classes must have a virtual destructor to
allow objects of derived classes to perform proper cleanup if they are
deleted from a base pointer.
Dynamic cast is the best for your description of problem,
but I just want to add that you can find the class type with:
#include <typeinfo>
...
string s = typeid(YourClass).name()
This is called RTTI, but you almost surely want to reconsider your design here, because finding the type and doing special things based on it makes your code more brittle.
Just to be complete, I'll build off of Robocide and point out that typeid can be used alone without using name():
#include <typeinfo>
#include <iostream>
using namespace std;
class A {
public:
virtual ~A() = default; // We're not polymorphic unless we
// have a virtual function.
};
class B : public A { } ;
class C : public A { } ;
int
main(int argc, char* argv[])
{
B b;
A& a = b;
cout << "a is B: " << boolalpha << (typeid(a) == typeid(B)) << endl;
cout << "a is C: " << boolalpha << (typeid(a) == typeid(C)) << endl;
cout << "b is B: " << boolalpha << (typeid(b) == typeid(B)) << endl;
cout << "b is A: " << boolalpha << (typeid(b) == typeid(A)) << endl;
cout << "b is C: " << boolalpha << (typeid(b) == typeid(C)) << endl;
}
Output:
a is B: true
a is C: false
b is B: true
b is A: false
b is C: false
Probably embed into your objects an ID "tag" and use it to distinguish between objects of class A and objects of class B.
This however shows a flaw in the design. Ideally those methods in B which A doesn't have, should be part of A but left empty, and B overwrites them. This does away with the class-specific code and is more in the spirit of OOP.
You are looking for dynamic_cast<B*>(pointer)
Because your class is not polymorphic. Try:
struct BaseClas { int base; virtual ~BaseClas(){} };
class Derived1 : public BaseClas { int derived1; };
Now BaseClas is polymorphic. I changed class to struct because the members of a struct are public by default.
Your description is a little confusing.
Generally speaking, though some C++ implementations have mechanisms for it, you're not supposed to ask about the type. Instead, you are supposed to do a dynamic_cast on the pointer to A. What this will do is that at runtime, the actual contents of the pointer to A will be checked. If you have a B, you'll get your pointer to B. Otherwise, you'll get an exception or null.
As others indicated you can use dynamic_cast. But generally using dynamic_cast for finding out the type of the derived class you are working upon indicates the bad design. If you are overriding a function that takes pointer of A as the parameter then it should be able to work with the methods/data of class A itself and should not depend on the the data of class B. In your case instead of overriding if you are sure that the method you are writing will work with only class B, then you should write a new method in class B.
If you can access boost library, maybe type_id_with_cvr() function is what you need, which can provide data type without removing const, volatile, & and && modifiers. Here is an simple example in C++11:
#include <iostream>
#include <boost/type_index.hpp>
int a;
int& ff()
{
return a;
}
int main() {
ff() = 10;
using boost::typeindex::type_id_with_cvr;
std::cout << type_id_with_cvr<int&>().pretty_name() << std::endl;
std::cout << type_id_with_cvr<decltype(ff())>().pretty_name() << std::endl;
std::cout << typeid(ff()).name() << std::endl;
}
Hope this is useful.
Use overloaded functions. Does not require dynamic_cast or even RTTI support:
class A {};
class B : public A {};
class Foo {
public:
void Bar(A& a) {
// do something
}
void Bar(B& b) {
Bar(static_cast<A&>(b));
// do B specific stuff
}
};
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*.
Base class
class Base
{
public:
Base()=default;
virtual void f(){cout << "base class\n";}
virtual ~Base(){}
};
Derived class
class Derive : public Base
{
public:
Derive()=default;
void f() override {cout << "derived class\n";}
};
main function
int main()
{
Base* bsd = new Base;
Derive* dru = new Derive;
if(Derive* drd=dynamic_cast<Derive*>(bsd)){
drd->f();
cout << "downcast successful\n";
}else{
cout << "downcast failed\n";
}
if(Base* bsu=dynamic_cast<Base*>(dru)){
bsu->f();
cout << "upcast successful\n";
}else{
cout << "upcast failed\n";
}
delete bsd;
delete dru;
}
It turns out upcast works fine, while downcast failed. It seems makes sense that way. If the derived class contain member objects that are not declared in the base class and do not have default constructors, what gonna happen during downcast?
Besides, the target pointer *drd(*bsd) created through dynamic_cast points to the same object with the pointer *bsu(*dru) to be cast. So delete once will be enough. We will not have a dangling pointer, right?
Casting does not create anything new or changes objects in any way. Casting changes the interpretation of an existing object, so if an object is not a Derive, there is no way to make it a Derive through casting.
Note that Derive is also a Base, because inheriting creates an "is a" relationship. That's why upcasting works: all it does is telling the compiler that it should treat the pointed to object as Base, even though the object is actually Derive.
It makes no difference in your program, so here is an illustration of what the cast does:
class Derive : public Base
{
public:
Derive()=default;
void f() override {cout << "derived class\n";}
void added() {cout << "hello" << endl; }
};
dru->added(); // Works
Base* bsu=dynamic_cast<Base*>(dru);
bsu->added(); // Does not compile
Essentially, the cast "hides" added interfaces from the compiler, ordering it to treat a Derive object as if it were Base. Of course, the overrides continue to be called correctly, because the overriden member-functions are part of the Base's interface.
I'm not sure I got your question right, but yes, you can safely delete a derived class using a base pointer, if the destructor is virtual.
A "dangling pointer" is something different: After you have deleted bsd and dru, you can not use these pointers anymore, they have become dangling pointers, because they point to deleted memory that you don't own anymore.
dynamic_cast checks run-time type check and provides a safe conversion. If a meaningful conversion is possible then you'd get a valid object after downcast. As you pointed out, in your example the underlying object was of "base class". Run time type check failed. However if the underlying object was of "derieved class" dynamic_cast would have succeeded. ex:
class CBase
{
public:
CBase(void);
virtual ~CBase(void);
virtual void identify()
{
std::cout << "base class" << std::endl;
}
};
class CDerieved : public CBase
{
public:
CDerieved(void);
virtual ~CDerieved(void);
virtual void identify()
{
std::cout << "Derieved class" << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CDerieved* pderieved = new CDerieved;
pderieved->identify();
CBase* pb = static_cast<CBase*>(pderieved);
pb->identify();
CDerieved* pd1 = dynamic_cast<CDerieved*>(pb);
pd1->identify();
return 0;
}
The above code will succeed.
But please remember, if you find needing a downcast, then the design needs to be revised.
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.
How the compiler do composition in inheritance?
suppose that I create an object of a derived class where both the base class and the derived class contain via composition object of other classes. I want some example to explain constructors and destructors.
I'm not going to make this overly easy for you, given it does indeed look like homework. If you can think through and understand what's below - good luck to you....
The base class's constructor is invoked, which will - for each member variable in order of declaration in the base class - call either the constructor corresponding to arguments specified in the base class initialisation list or the default constructor if any (otherwise the member's left uninitialised, though sometimes e.g. earlier zero-initalisation of the memory the object is contained in - perhaps due to new (p) T() notation or being static - will guarantee specific values anyway). Then, the derived constructor does the same for its own data members. Destruction happens in reverse order.
If you need to demonstrate the basic principles, you could use some variants of:
struct M { // Marker
int id;
M(int i) : id(i) { cout << "\tconstruction M" <<id<< endl; }
~M() { cout << "\tdestruction M" <<id<< endl; }
};
struct B { //Base
M mb;
B() : mb(1) { cout << "construction B (body finished)" << endl; }
~B() { cout << "destruction B (body finished)" << endl; }
};
struct D : public B { //Derived
M md;
D() : md(2) { cout << "construction D (body finished)" << endl; }
~D() { cout << "destruction D (body finished)" << endl; }
};
Of course, it's simplified, but it shows that the base is constructed before the derived, and members are constructed before constructore body is executed. It shows as well as that destruction is performed in reverse order of construction.
But that's only the most obvious. You should aslo show examples demonstrating in which order members are constructed when there are severals, and what happens in multiple inheritance, as well as the case of static members.
Are there any cases where we do down casting of objects?
If we do, why?
I have observed a way of hiding implementation using the below code. Is this the correct way to do? Is there any better way to achieve the same.
class A{
public:
A();
virtual ~A();
//exposed virtual functions
};
class AImpl : public A{
public:
AImpl(A *obj);
virtual ~AImpl();
//exposed virtual functions++
};
class Helper{ //utility class so i am making constructor and assignment operator as private
public:
static bool doWork(A *obj){
AImpl *objImpl = dynamic_cast<AImpl *> (obj);
return doWork(objImpl); // some internal function
}
private:
Helper();
Helper(const Helper& obj);
const Helper& operator=(const Helper& obj);
};
The question still does not makes sense. I agree. I still have not figured out a proper way of hiding the implementation details from the client.
UncleBens
I termed this thing wrongly as Object slicing. Basically, I was referring to this (Object Slicing) as the information related to derived part is missing.
S.Soni
Thanks for giving a wonderful explaination. Now, I can really put forward question.
Consider a clients perspective. The only class which are visible to him is class A and the Helper class (because I have hidden implementation behind AImpl
Client has to write the following code as he is unaware of AImpl class
int main(){
A *a = new A();
Helper.doWork(a);
// ...
}
As you said AImpl * in this case will actually be pointing to the base class object, which is wrong (you have explained it with a great example), so this approach of hiding implementation is not correct.
Any attempt to access a derived class member function will result in a crash (and correctly so).
How should I go about hiding the implementation in this case? This is a design problem now?
**Are there any cases where we do down casting of objects**
The purpose of dynamic_cast is to perform casts on polymorphic types. For
example, given two polymorphic classes Band D, with D derived from B, a
dynamic_cast can always cast a D* pointer into a B* pointer. This is because a base
pointer can always point to a derived object. But a dynamic_cast can cast a B* pointer
into a D* pointer only if the object being pointed to actually is a D object.
**`Is there any better way to achieve the same`**
Perhaps the most important of the new casting operators is dynamic_cast. The
dynamic_cast performs a run-time cast that verifies the validity of a cast.
1) Your class is not polymorphic.A class that declares or inherits a virtual function is called a polymorphic class
2) Syntax of dynamic_cast is dynamic__cast (expr)
1st Edit :
Try like this , it will work
class A
{
public:
A();
virtual ~A();// Notice here i have put virtual
};
class AImpl : public A
{
public:
AImpl(A *obj);
~AImpl();
};
class Helper
{
public:
Helper(){}
static bool doWork(A *obj)
{
AImpl *objImpl = dynamic_cast<AImpl*> (obj);
return true;
}
};
Study this example :
class Base
{
public:
virtual void f() { cout << "Inside Base\n"; }
// ...
};
class Derived: public Base
{
public:
void f() { cout << "Inside Derived\n"; }
};
int main()
{
Base *bp, b_ob;
Derived *dp, d_ob;
dp = dynamic_cast<Derived *> (&d_ob);
if(dp) {
cout << "Cast from Derived * to Derived * OK.\n";
dp->f();
} else
cout << "Error\n";
cout << endl;
bp = dynamic_cast<Base *> (&d_ob);
if(bp) {
cout << "Cast from Derived * to Base * OK.\n";
bp->f();
} else
cout << "Error\n";
cout << endl;
bp = dynamic_cast<Base *> (&b_ob);
if(bp) {
cout << "Cast from Base * to Base * OK.\n";
bp->f();
} else
cout << "Error\n";
cout << endl;
dp = dynamic_cast<Derived *> (&b_ob);
if(dp)
cout << "Error\n";
else
cout << "Cast from Base * to Derived * not OK.\n";
cout << endl;
bp = &d_ob; // bp points to Derived object
dp = dynamic_cast<Derived *> (bp);
if(dp) {
cout << "Casting bp to a Derived * OK\n" <<
"because bp is really pointing\n" <<
"to a Derived object.\n";
dp->f();
} else
cout << "Error\n";
cout << endl;
bp = &b_ob; // bp points to Base object
dp = dynamic_cast<Derived *> (bp);
if(dp)
cout << "Error";
else {
cout << "Now casting bp to a Derived *\n" <<
"is not OK because bp is really \n" <<
"pointing to a Base object.\n";
}
cout << endl;
dp = &d_ob; // dp points to Derived object
bp = dynamic_cast<Base *> (dp);
if(bp) {
cout << "Casting dp to a Base * is OK.\n";
bp->f();
} else
cout << "Error\n";
return 0;
}
From your code and the information that the passed in pointer actually points to an A, and not an AImpl, also the constructor AImpl that accepts an A*, I gather that what you want it:
class Helper{
public:
static bool doWork(A *obj){
AImpl objImpl(obj); //construct an AImpl instance, using available constructor
return doWork(&objImpl); // some internal function
}
};
There is no way to cast a base instance into an instance of a derived class (where would the missing derived part come from??).
Well, if the following holds true (not the only valid reasons, but a common one):
you have a MVC like architecture
you want to hide the implementation details from client code (no-na...)
you need to pass some references from core to client-code (handles of all sorts, etc.)
the only valid implementation of the public interfaces must be in the core of the MVC part
then using this way is quite common.
However, if it is simply not allowed to use any other implementation (because only your library core may implement the interface), then asserting the type would be nice too; this would provide a nice landing in the debugger or crash-dump for any user of the library who messed with it in a way it should not be done. Of course, the documentation should clearly indicate that deriving from A is a bad idea.
Your example code contains at least 4 syntax errors, so it's hard to judge what you're trying to do.
And it logically won't work either. You have a class AImpl that inherits A, then a member function that takes an A and appears to try to dynamic-cast it to an AImpl. But it isn't an AImpl, because it's just an A, as that is how the parameter is declared. If you were to pass an instance of AImpl to that function, it would be sliced down to just an A.
You could make it a reference or pointer to an A, and then it could be an AImpl. Dynamic casts are only ever of use on references or pointers.
Down-casting is used when we have a variable or parameter that has the static type of a base class but we logically know that it is (or might be) of a derived class. It is avoided wherever possible because it means that the compilation process is not able to completely check the type-correctness of the program, i.e. the answer to the question "are you trying to put a square peg into a round hole" cannot be fully answered until runtime.
Update after question was edited
It sounds like you want clients of your library to have access to a limited interface to an object, A, but when they pass it to a function in your library you will have access to the full interface. You could just use friend for this.
class A
{
friend class LibraryThing;
void visibleToLibraryThing();
public:
// ctor, etc.
void visibleToAll();
};
class LibraryThing
{
public:
void foo(A &a)
{
a.visibleToLibraryThing();
}
};
The LibraryThing class can access the private members of A, because it is declared as a friend of A.
The downside is that LibraryThing can access everything in A, so it means that as the author of the library, you won't be able to benefit from encapsulation. Only users of your library will.
You can use PIMPL to hide implementation details, mask dependencies, and speed up builds.
http://www.gotw.ca/gotw/028.htm
http://www.ddj.com/cpp/205918714
http://www.gotw.ca/gotw/024.htm