我正在尝试一个基本的东西,有两个类和一个自由函数。首先,我有两个班级:
struct BASE{
BASE(int a = 0):a_(a){};
virtual ~BASE(){};
virtual void foo(){std::cout << "BASE " << std::endl;}
int a_;
};
struct DERIVED: public BASE{
DERIVED():BASE(){};
void foo(){std::cout << "DERIVED " << std::endl;}
};
然后我填写std :: vector(或boost :: ptr_vector)
std::vector<BASE* > vec;
vec.push_back( new BASE(2));
vec.push_back( new DERIVED);
如果我调用我的函数foo,没有pb虚拟的东西效果很好, 但如果我创建两个自由函数:
void foo(BASE* a, DERIVED* b){
std::cout << " mix base/derived " << std::endl;
}
void foo(BASE* a, BASE* b){
std::cout << " full base " << std::endl;
}
如果我这样做
foo(vec[0], vec[1]); //failed
我会收到消息
full base
这是合乎逻辑的,因为我有BASE *的矢量,但无论如何都存在 能够很好地调用我的免费功能吗?我需要继承,所以我不能真正分开这两个类,因为我必须填写这个容器
此外,最后我的矢量会随机填满,所以我无法提前知道如何正确投射。
答案 0 :(得分:2)
获得解决方法的最简单(也是最快)的方法是引入一个虚拟函数来唯一标识派生类(使用int
,enum
值或typeid
)。所以稍后你可以调用它来实现你在BASE*
后面得到的确切派生类(或者可能是基础),并对dynamic_cast
做dynamic_cast
。
您没有提供有关您要解决的问题的详细信息...如果您想要实现Double Dispatch(或某种类型),请确保您已完成对现有解决方案的全面解决。 ..
但通常情况下,如果您需要{{1}},则表示您设计的错误(域名的OOP模型)......
答案 1 :(得分:0)
正如您事先并不知道您的vec[i]
是什么,编译器也不是。函数重载解析是一个编译时进程,而多态 - 运行时。
因此它调用void foo(BASE* a, BASE* b)
版本。
换句话说,除非您使用dynamic_cast
尝试强制转换为每个可能的派生类,否则您想要做的事情是不可能的。如果对象类型错误,它将返回0
。
然而,很多人会争辩说使用dynamic_cast
表明设计不好。它也很贵。
答案 2 :(得分:0)
你需要动态调度,如下所示:
void foo(BASE *a, BASE *b) {
if (DERIVED *bb = dynamic_cast<DERIVED*>(b)) {
foo(a, bb);
} else {
std::cout << " full base " << std::endl;
}
}
如果您不想使用dynamic_cast
,可以向BASE
添加一个虚函数,该函数将返回某种形式的类标识符(例如enum
),覆盖此在每个派生类中,然后根据此函数的返回值(以及static_cast
)分叉调用。