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来知道将它强制转换到哪个派生类?
您需要在这两个类中使
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
号