关于c ++:如何从基类指针调用派生类方法?

How to call derived class method from base class pointer?

我有一个类似以下的班级结构

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
class A
{
public:
    A(void);
    ~A(void);

    void DoSomething(int i)
    {
        std::cout <<"Hello A" << i << std::endl;
    }
};

class B : public A
{
public:
    B(void);
    ~B(void);

    void DoSomething(int i)
    {
        std::cout <<"Hello B" << i << std::endl;
    }
};

class Ad : public A
{
public:
    Ad(void);
    ~Ad(void);
};

class Bd : public B
{
public:
    Bd(void);  
    ~Bd(void);
};

我想将派生类的实例存储在一个容器(标准映射)中,作为一个*的集合,然后遍历容器并为每个实例调用方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include"A.h"
#include"B.h"
#include"Ad.h"
#include"Bd.h"
#include <map>
int main(int argc, char** argv)
{
    std::map<int,A*> objectmap;
    objectmap[1] = new Ad();
    objectmap[2] = new Bd();

    for (std::map<int,A*>::iterator itrobject = objectmap.begin();
         itrobject!=objectmap.end(); itrobject++)
    {
        itrobject->second->DoSomething(1);
    }
    return 0;
}

上述代码生成以下输出。

1
2
Hello A1
Hello A1

在我期待的地方

1
2
Hello A1
Hello B1

因为我希望b中的dosomething隐藏a中的dosomething,并且因为我正在存储指针,所以我希望不进行对象切片(在调试器中查看对象指针会显示对象尚未切片)。

我尝试了向下强制转换和动态强制转换指向b的指针,但是它会将bd的数据成员分割开。

在不将指针强制转换到bd的情况下,是否有任何方法可以调用b::dosomething?如果没有,如果我有很多B的派生类(如bda、bdb、bdc等),有没有办法使用rtti来知道将它强制转换到哪个派生类?


您需要在这两个类中使DoSomething()成为virtual函数,以获得您所追求的多态行为:

1
virtual void DoSomething(int i) { ...

您不需要在每个子类中实现虚拟函数,如下例所示:

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
#include <iostream>

class A {
    public:
        virtual void print_me(void) {
            std::cout <<"I'm A" << std::endl;
        }

        virtual ~A() {}
};

class B : public A {
    public:
        virtual void print_me(void) {
            std::cout <<"I'm B" << std::endl;
        }
};

class C : public A {
};

int main() {

    A a;
    B b;
    C c;

    A* p = &a;
    p->print_me();

    p = &b;
    p->print_me();

    p = &c;
    p->print_me();

    return 0;
}

输出:

I'm A
I'm B
I'm A