【问题标题】:How to design base and derived classes with different return type?如何设计具有不同返回类型的基类和派生类?
【发布时间】:2015-03-31 15:08:51
【问题描述】:

我有一个基类Attr(属性),它有两个派生类NomAttr(名义属性)和NumAttr(数值属性)。

每个都有一个name 成员,它总是字符串类型。

但是,他们的value 成员不同:对于NomAttr,我想获得string 类型的value,但对于NumAttr,我想获得double 类型的value .

虚拟函数不允许不同的返回类型,所以我有点卡在这里。 (最初我绘制下面的 UML 来模拟我的意图。)


很多人要求我展示真正的问题。这是一个全局视图:

这是一个机器学习者。 Attr 是数据集中实例的一部分:
DataSetIns(实例)的列表组成。
InsAttrs 的列表组成,Attrs 的计数和每个 Attr 的类型在运行时是已知的,从用户提供的带有命令行参数的数据文件中解析。
给你:

【问题讨论】:

  • 你可以使用模板。
  • 我建议返回 boost any 或 boost variant。
  • 您能说明您要解决的真正问题以及使用Attr 的上下文吗? C++ 是强类型的,不直接支持您想要做的事情,但根据实际需要,您可以使用各种机制(可能是静态或动态多态性)。
  • @MarkB 更像是静态类型的。
  • @MarkB 请查看更新。

标签: c++ uml virtual


【解决方案1】:

因此,根据您的更新,我认为您根本不需要任何继承来处理您的 attr。相反,让基础 Attr 将值直接包含为 boost::variant<double, std::string> 并且由于您知道它将是什么类型,您可以简单地从每个属性的变体中获取正确的类型。

【讨论】:

  • 谢谢。我需要试试这个。
【解决方案2】:

使用模板:

#include <iostream>
#include <string>

template <typename T> class Attribute{
public:
    Attribute() : mAttr(T()) { }
    Attribute(T pAttr) : mAttr(pAttr) { }
    T getAttr() { return mAttr; }
private:
    T mAttr;
};

class NumAttr : public Attribute<int>{
public:
    NumAttr() : Attribute<int>(0) { }
    NumAttr(int pAttr) : Attribute<int>(pAttr) { }
};

class NomAttr : public Attribute<std::string>{
public:
    NomAttr() : Attribute<std::string>(std::string()) { }
    NomAttr(std::string pAttr) : Attribute<std::string>(pAttr) { }
};
int main(void){
    NomAttr name(std::string("test"));
    NumAttr number(1);
    std::cout << "Name: " << name.getAttr() << std::endl;
    std::cout << "Number: " << number.getAttr() << std::endl;
}

请注意,实际上不需要派生类,您可以使用 Attribute&lt;int&gt;Attribute&lt;std::string&gt; 或任何其他您需要的类型。

编辑:如果在编译时不知道类型,这将不起作用,请参阅@MarkB 答案。

【讨论】:

    【解决方案3】:

    其实你只需要一个template derived class

    #include <iostream>
    #include <string>
    using namespace std;
    
    template <typename T>
    class Base
    {
    public:
        virtual T getValue() = 0;
    protected:
        T value;
    };
    
    template<typename T>
    class Derived : public Base<T>
    {
    public:
        Derived(T v)
        {
            value = v;
        }
        T getValue()
        {
            return value;
        }
    };
    
    int main()
    {
        Derived<string> d1 = Derived<string>("test");
        Derived<double> d2 = Derived<double>(3.14);
    
        cout << d1.getValue() << endl;
        cout << d2.getValue() << endl;
    
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      要么使用其他用户建议的模板,要么不返回值,而是通过引用设置值。

      伪代码 EX:

      //this code has your problem
      virtual int func();
      
      int func(int a) override
      {return a + 3};
      int a = func(3);//a will be 6
      
      //this code does not
      virtual void procedure();
      
      void procedure(int a, int* b) override
      {*b=a+3};
      int a;
      func(3,&a);//a will be 6
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多