2

我有一个包含 int、float 或 string 的容器对象。我有一个以类似方式处理的这些容器的队列。目前我对不同的数据类型有单独的吸气剂。这并不是特别优雅,因为每个容器实例一次只能保存一种数据类型。

class MyContainer
{
    MyContainer(float value);
    MyContainer(int value);
    MyContainer(string value);

    int getIntValue();
    float getFloatValue();
    string getStringValue();
}

void processContainer(MyContainer& container)
{
    // the following will not work, but is desired:
    process(container->getValue()); // compilation error
}

void process(int value) {}
void process(float value) {}
void process(string value) {}

有没有办法可以利用上述过程方法的参数重载?例如,某种方式可以让我简单地调用 process(container->getValue())?

4

6 回答 6

3

您可以使用模板特征将模板代码限制为字符串、浮点数和整数类型。

于 2013-05-02T20:09:49.150 回答
2

另一种方法是使用Visitor模式。这允许您根据类型动态调度。

struct Float;
struct Integer;

struct ContainerVisitor {
    virtual void visit(Float& value) = 0;
    virtual void visit(Integer& value) = 0;
    // etc.
};

struct Container {
    virtual void accept(ContainerVisitor& visitor) = 0;
};

struct Integer : Container{
    virtual void accept(ContainerVisitor& visitor) {
        visitor.visit(*this);
    }
};

struct Float : Container{
    virtual void accept(ContainerVisitor& visitor) {
        visitor.visit(*this);
    }
};

然后,无论您要执行什么操作,都将其放入派生自的类中ContainerVisitor

struct Processor : ContainerVisitor {
    virtual void visit(Float& value) {
        // equivalent of your process(float);
    }
    virtual void visit(Integer& value) {
        // equivalent of your process(int);
    }
};

像这样使用:

int main() {
    Processor processor;

    Integer i;
    Float f;

    i.accept(processor);
    f.accept(processor);
}
于 2013-05-02T20:42:14.323 回答
2

如果我正确理解你的目的,你想让 MyContainer 持有 int、float 或 string。

在这种情况下,您肯定需要模板来定义您的类:

template<typename T>
class MyContainer 
{
private:
    T _value;

    MyContainer(T value)
    {
        _value = value;
    }

public:
    T GetValue()
    {
        return _value;
    }
}

你可以像这样定义它的实例:

MyContainer<float>  v1(10.11); 
MyContainer<int>  v2(10);
MyContainer<string>  v3("dddddd");

现在您可以使用 GetValue 来获取不同类型的值:

v1.GetValue();
v2.GetValue();
v3.GetValue();
于 2013-05-02T20:36:10.097 回答
1

问题是知道应该processContainerMyContainer. 由于这些知识被封装在 中MyContainer,也许进程调用也应该是,或者至少是对它的调度。那是:

class MyContainer
{
    MyContainer(float value);
    MyContainer(int value);
    MyContainer(string value);

    invokeProcess()
    {
       // call correct overload of process based on value stored
    }

    int getIntValue();
    float getFloatValue();
    string getStringValue();
}

void processContainer(MyContainer& container)
{
    container->invokeProcess(); 
}

您还可以使用多态性和 MyContainer 的几个子类来实现这一点。您基本上会将切换逻辑从invokeProcess 内部的case 语句转换为它外部的虚函数查找。

其他人提到了工会。你真的需要一个有区别的 union,包括一个 enum 来知道值是什么类型。

于 2013-05-02T20:10:46.687 回答
0

union如果您提前知道每个值的类型,A可能会起作用。如果您可以使用 Qt 库,QVariant是一个选项。

于 2013-05-02T20:10:08.027 回答
0

不幸的是,可能不是,至少不是以任何优雅的方式。C++ 不允许仅返回类型不同的重载函数,因此每个数据类型必须有一个 getter。您可以拥有三个名称相同的函数,它们接收您想要返回的类型的虚拟变量,或者将指针作为参数并以这种方式返回值,但这些选项都没有让您更接近process(container->getValue()).

于 2013-05-02T20:16:02.967 回答