根据参数类型,只会调用容器的匹配对象

based on argument type, only matching object of container will be called

本文关键字:对象 调用 参数 类型      更新时间:2023-10-16

all,我有一个对象的容器,例如,

class ShapeBase {};
class Rect: public Shape {
void set(class Diag diag);
};
class Circle: public Shape {
void set(class Radi radi);
};

现在我有一个应用程序类来调用这个形状列表。我的意图是列表的元素将仅根据参数类型调用。

像这样的东西。

 class application {
    typedef std::list<ShapeBase*> List;
    List shapeList; 
    void set(class ???) {
    for (List::iterator it = shapeList.begin(); it != shapeList.end(); ++it)
    {
        // with in the loop of all objects in list,
        // only object with matching argument will be called  
        set(class ???);
    };

这样应用程序类根本不知道具体的形状。

如何在C++做到这一点?

不幸的是,在设置对象列表时,您尝试对对象列表执行的操作对于定义相当困难。setup 的一个问题是在编译时没有要Diag Rect的关联,因此您必须告诉编译器 Rectangles 需要特定的构造函数参数。一种解决方案是模板化application::set方法,然后为每个形状专门化该模板。

下面是一些伪代码来做到这一点(不保证编译(:

template<typename ShapeType>
void fillShapeTypeList(std::list<ShapeType*> fillList) {
    for (List::iterator it = this.shapeList.begin(); 
              it != this.shapeList.end(); ++it) {
        if (ShapeType *shape = dynamic_cast<ShapeType>(*it)) {
            fillList.push_back(shape);
        }
    }
}
template<typename ShapeType, typename ShapeSetter>
void set(ShapeSetter setter) {
    std::list<ShapeType*> fillList;
    fillShapeTypeList(fillList);
    for (std::list<ShapeType*>::iterator it = this.shapeList.begin(); 
             it != this.shapeList.end(); ++it) {
        (*it)->set(setter);
    }
}
void set(Diag setter) {
    set<Rect, Diag>(setter);
}
void set(Radi setter) {
    set<Circle, Radi>(setter);
}

还有另一种更复杂的方法可以让它工作,而无需使用"替换失败不是错误"模式的Rect/Circle特定二传手 - 但在这种情况下不值得付出努力。

一般来说,你应该问问自己,当如何让编译器做你想做的事并不明显时,你是否在做正确的事情。在这种情况下,最好使用应用程序注册对象的回调,或者使指定类型的所有形状查看中心对象以获取大小信息。