identifying whether a class is derived from another specific class?

HI,

I would like to know if there is a way to know if a given class is a derived class of another class -

ex:
class a
{
// code
};
class b: public a
{
//
};

int main()
{
b x;
return 0;
}

In main how do i prove that object x is an object of the class which is derived from class a.

I am not sure if typeid would help in this case.
Can you prove it with errors?
1
2
b x;
a &y = b;
If b is derived from a, this will work. Otherwise you will get an error.
Last edited on
Thanks for the reply...

it would give a compilation error.
i am more of looking for runtime output.... i did try with dynamic_cast though... alas it gives me a compilation error.
Last edited on
Oh, I would suggest something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <class Super, class Sub>
struct AssertSuperSubClass
{
    ~AssertSuperSubClass()
    {
        Super * s = (Sub *) 0;
    }
};

class A {};
class B : public A {};
class C {};

int main()
{
    AssertSuperSubClass<A, B>(); // ok!
    AssertSuperSubClass<A, C>(); // error!

    return 0;
}

But apparently this is not what you want.
What exactly are you trying to achieve?
Last edited on
yes, i do not have any use case of it...

But i was wondering if, is there some kind of provision in the language itself to know that a given object belongs to a class which is
inherited from some other know class.
In c++ there are well known associations from base class to derived class , but i havent come across something which gives association in other direction. i am not sure if this is needed at all.

i am looking answers for these question -
is there some kind of such association exists?
can this be achieved during run time?

Yes your program does answer my question, if compilation error is accepted.
If b inherits a member form a, it will have a different size. When compiling the code, the sizeof() function will evaluate to a different value. If there are no inherited data members, though,then there will be no size difference, making this problem trickier.
Ok, this one is better:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

template <class Super, class Sub>
struct IsSuperSubClass
{
    static bool ConversionTest(const Super *) { return  true; }
    static bool ConversionTest(const void  *) { return false; }

    static const Sub * p;
    static const bool VALUE;
};

template <class Super, class Sub>
const Sub * IsSuperSubClass<Super, Sub>::p = 0;

template <class Super, class Sub>
const bool IsSuperSubClass<Super, Sub>::VALUE =
    IsSuperSubClass<Super, Sub>::ConversionTest(p);

class A {};
class B : public A {};
class C {};

int main()
{
    std::cout << IsSuperSubClass<A, B>::VALUE << std::endl;
    std::cout << IsSuperSubClass<A, C>::VALUE << std::endl;

    return 0;
}

Though, I think this is not what you want either.
If I understand correctly, what you want is reflection.
C++ doesn't have a built-in reflection mechanism.
The most straightforward way to do this is to provide
that information yourself, in order to be able to use it later:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <typeinfo>
#include <iostream>
#include <string>
#include <list>
#include <map>

struct ClassInfo
{
    std::string name;

    std::list<const ClassInfo *> super_classes;
    std::list<const ClassInfo *> sub_classes;

    //...
};

class A {};
class B : public A {};

class ClassInfoManager
{
    static std::map<std::string, const ClassInfo *> class_info_data;

public:

    static void Init()
    {
        ClassInfo * ci_A = new ClassInfo;
        ClassInfo * ci_B = new ClassInfo;

        ci_A->name = "A";
        ci_B->name = "B";

        ci_A->sub_classes.push_back(ci_B);
        ci_B->super_classes.push_back(ci_A);

        class_info_data[typeid(A).name()] = ci_A;
        class_info_data[typeid(B).name()] = ci_B;
    }

    static void Release()
    {
        std::map<std::string, const ClassInfo *>::iterator cur_it;
        std::map<std::string, const ClassInfo *>::iterator end_it;

        cur_it = class_info_data.begin();
        end_it = class_info_data.end();

        while (cur_it != end_it) { delete cur_it->second; ++cur_it; }
    }

    static const ClassInfo & Get(const std::string & type_name)
    {
        return *class_info_data[type_name];
    }
};

std::map<std::string, const ClassInfo *> ClassInfoManager::class_info_data;

int main()
{
    ClassInfoManager::Init();

    A a;
    B b;

    std::cout << "a's type ("
        << ClassInfoManager::Get(typeid(a).name()).name << ") is a superclass of "
        << ClassInfoManager::Get(typeid(a).name()).sub_classes.front()->name
        << std::endl;

    std::cout << "b's type ("
        << ClassInfoManager::Get(typeid(b).name()).name << ") is a subclass   of "
        << ClassInfoManager::Get(typeid(b).name()).super_classes.front()->name
        << std::endl;

    ClassInfoManager::Release();

    return 0;
}

For more info on the subject, try googling "reflection c++".
Last edited on
@L B, i am not sure if sizeof operator is foolproof way of identifying the objects inheritance nature towards multiple known classes.

@m4ster r0shi,
Yes, indeed i was looking for something similar to reflection.
since there are no such in-built facility available in c++, self implementation is the way forward.

thanks for the link. my question is duely answered.
Topic archived. No new replies allowed.