Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking the object type in C++11

I have class B that inherits from A.

class A
{
};

class B : public A
{
};

And I have three objects.

A* a = new A();
A* a2 = new B();
B* b = new B();

I'd like to if check a is object of type A, a2 is object of type B (not A), and b is object of type B.

I tried typed comparison, but it doesn't give me correct answer.

cout << (typeid(*a) == typeid(A)) << endl; // -> 1
cout << (typeid(*a2) == typeid(A)) << endl; // -> 1
cout << (typeid(*b) == typeid(A)) << endl; // -> 0

cout << (typeid(*a) == typeid(B)) << endl; // -> 0
cout << (typeid(*a2) == typeid(B)) << endl; // -> 0
cout << (typeid(*b) == typeid(B)) << endl; // -> 1

I tried dynamic casting, but I got compile error.

B* derived = dynamic_cast<B*>(a);
if (derived) {
    cout << "a is B";
}
derived = dynamic_cast<B*>(a2);
if (derived) {
    cout << "a2 is B";
}
derived = dynamic_cast<B*>(b);
if (derived) {
    cout << "b is B";
}

typename.cpp: In function 'int main(int, char**)':
typename.cpp:27:36: error: cannot dynamic_cast 'a' (of type 'class A*') to type 'class B*' (source type is not polymorphic)
     B* derived = dynamic_cast<B*>(a);
                                    ^
typename.cpp:31:34: error: cannot dynamic_cast 'a2' (of type 'class A*') to type 'class B*' (source type is not polymorphic)
     derived = dynamic_cast<B*>(a2);

I used static casting, but I got the answer wrong.

B* derived = static_cast<B*>(a);
if (derived) {
    cout << "a is B"; // -> YES
}
derived = static_cast<B*>(a2);
if (derived) {
    cout << "a2 is B"; // -> YES
}
derived = dynamic_cast<B*>(b);
if (derived) {
    cout << "b is B"; // -> YES
}

How can I correctly identify the object type in C++11?

like image 307
prosseek Avatar asked Jun 20 '13 02:06

prosseek


People also ask

How to check the type of an object in C?

Thus, there are certain ways using which the Object in C# can be checked which are as follows : 1 GetType () is a method that is quite frequently used to check the object type in C 2 . This method is used to work at... 3 Get type () method is a method in the object class that is used for making a referencing for an instance of the class. More ...

How to check the type of an object being derived?

C# object being derived have some methods and abilities to reference and dereference any object of the base type. Referencing of an object in both the cases of derived and base classes plays an important role for checking the object type being created. Casting with the base class object is mandatory to make it compatible to check the object type.

What is an object in C programming language?

C# is a programming language that considers object as the base class for all the derived classes in a program. All types get inherited from objects which are further used for performing some functionality by extending the properties of derived classes.

What should a compiler check before writing a program?

A compiler must check that the source program should follow the syntactic and semantic conventions of the source language and it should also check the type rules of the language. It allows the programmer to limit what types may be used in certain circumstances and assigns types to values.


1 Answers

Some classes are polymorphic, some are non-polymorphic.

A polymorphic class has one or more virtual functions (possibly inherited), a non-polymorphic class has zero virtual functions.

Your A and B are non-polymorphic.

A polymorphic version of A and B will exhibit the behaviour you want:

#include <iostream>
#include <typeinfo>

using namespace std;

struct A
{
    virtual ~A() {}; // add virtual function
};

class B : public A
{
};

A* a = new A();
A* a2 = new B();
B* b = new B();

int main()
{
    cout << (typeid(*a) == typeid(A)) << endl; // -> 1
    cout << (typeid(*a2) == typeid(A)) << endl; // -> 0 <-- CHANGED
    cout << (typeid(*b) == typeid(A)) << endl; // -> 0

    cout << (typeid(*a) == typeid(B)) << endl; // -> 0
    cout << (typeid(*a2) == typeid(B)) << endl; // -> 1 <-- CHANGED
    cout << (typeid(*b) == typeid(B)) << endl; // -> 1
}

Instances of a polymorphic class store the dynamic type of their most derived object at runtime.

(In your example a2 is of type pointer-to-A, and is pointing at an object of type A, however this object is only a base class subobject of the most dervived object of type B. What you want to get is the type of this most derived object B when querying a2. For this you need a polymorphic class.)

That is how polymorphic classes support dynamic_cast and typeid of the most derived object (as well as virtual function dispatch).

Non-polymorphic classes do not have this information, so they can only report the static type known at compile-time. Non-polymorphic classes are more compact and efficient then polymorphic classes. That is why not all C++ classes are polymorphic. The language leaves it up to the programmer to chose the tradeoff between performance and functionality. For example:

struct X { int x; };
struct Y : X {};
struct Z : Y {};

On my system non-polymorphic Z is sizeof(Z) == 4 bytes, same as an int.

struct X { int x; virtual ~X() {}; };
struct Y : X {};
struct Z : Y {};

Now after making Z polymorphic, sizeof(Z) == 16 bytes. So an array of Z is now 300% larger, because each Z instance has to store its type information at runtime.

like image 159
Andrew Tomazos Avatar answered Sep 30 '22 06:09

Andrew Tomazos