【问题标题】:Vector of objects of derived classes with different templates具有不同模板的派生类对象的向量
【发布时间】:2014-08-25 10:26:53
【问题描述】:

考虑下面的基类:

template <typename T>
class food {
public:
    T quantity;
};

现在派生两个具有不同模板实例的类:

class cheese: public food<float> {
}
class chocolate: public food<int> {
}

在主函数中,我需要创建一个“食物”实例列表

int main () {
    vector<food*> bucket;
}

因为我不知道什么样的食物会被扔进桶里。但是,编译这段代码会产生错误:

error: missing template arguments before ‘*’ token

那么,我该怎么办呢?


现在我需要为派生类定义成员函数:

class cheese: public food<float> {
    float get_q() {return quantity};
}
class chocolate: public food<int> {
    int get_q() {return quantity};
}

问题是,如果我调用,编译器会说类 food 没有成员 get_q:

bucket.push_back(new cheese);
bucket.push_back(new chocolate);
bucket[0]->get_q();

在 main 中,即使我像这样更改 Quantity 界面

template <typename T>
class Quantity{
public:
    T quantity;
    virtual T get_q() = 0;
};

看来编译器确实需要查看food 中定义的get_q(),但如果food 不是模板,那是不可能的,对吧?

对不起,我是一个新的 C++ 程序员,很多事情对我来说不是很清楚......

【问题讨论】:

  • 模板参数是类型的一部分,所以它是不可能的。不过,您也许可以通过Boost Any 解决它。
  • 是的,boost::any 是不错的选择。
  • 感谢大家的解决方案。我真的需要在没有 Boost 库的情况下编写代码。在@RSahu 的解决方案中,似乎我必须在“food”类中虚拟定义派生类的所有成员函数,否则编译器会在编译时说该函数不是“food”的成员。跨度>

标签: c++ templates vector


【解决方案1】:
  • food&lt;float&gt;food&lt;int&gt; 是不同的类型,它们不能像多态一样使用。

  • food* 没有命名类型,因为模板需要一个参数(这是编译器告诉你的)

您要么为所有food&lt;&gt; 类型提供一个公共基础(如果类型确实相关,您可能需要它),或者您将需要某种类型擦除包装器,例如boost::anyboost::variant


boost::any 示例:

#include <vector>
#include <boost/any.hpp>

template <typename T>
class food {
public:
    T quantity;
};

class cheese: public food<float> {
};

class cholocate: public food<int> {
};


int main()
{
    std::vector<boost::any> v;
    v.push_back(food<float>());
    v.push_back(food<int>());
}

【讨论】:

    【解决方案2】:

    您可以制作一个不是类模板的基类food,并制作一个捕获数量的类模板。

    class food
    {
    };
    
    template <typename T>
    class Quantity{
    public:
        T quantity;
    };
    
    class cheese: public food, public Quantity<float> {
    };
    
    class cholocate: public food, public Quantity<int> {
    };
    
    
    int main()
    {
        std::vector<food*> v;
        v.push_back(new cheese);
        v.push_back(new cholocate);
    }
    

    更新,以回应 OP 关于需要添加的评论

    您可以添加get_quantity() 函数,例如:

    class food
    {
       public:
          virtual float get_quantity() const = 0;
    };
    
    class cheese: public food, public Quantity<float> {
       public:
          virtual float get_quantity() const
          {
             return this->quantity;
          }
    };
    
    class cholocate: public food, public Quantity<int> {
       public:
          virtual float get_quantity() const
          {
             return this->quantity; // Implicit conversion to float.
          }
    };
    

    【讨论】:

    • 谢谢。假设我在奶酪中添加float get_quantity(),在巧克力中添加int get_quantity()。并使用 v[0]->get_quantity 在 main 中调用它们。编译器说class food doesn't have member get_quantity。但我不能将它添加到food 类,因为返回值被覆盖。有解决办法吗?
    • @xna,请详细说明。你想添加什么?你想添加什么?
    • 我详细阐述了这个问题。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多