自由功能和继承

时间:2012-12-05 13:25:33

标签: c++

我正在尝试一个基本的东西,有两个类和一个自由函数。首先,我有两个班级:

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 *的矢量,但无论如何都存在 能够很好地调用我的免费功能吗?我需要继承,所以我不能真正分开这两个类,因为我必须填写这个容器

此外,最后我的矢量会随机填满,所以我无法提前知道如何正确投射。

3 个答案:

答案 0 :(得分:2)

获得解决方法的最简单(也是最快)的方法是引入一个虚拟函数来唯一标识派生类(使用intenum值或typeid)。所以稍后你可以调用它来实现你在BASE*后面得到的确切派生类(或者可能是基础),并对dynamic_castdynamic_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)分叉调用。