如何设计具有不同 return 类型的基础和派生 类?

How to design base and derived classes with different return type?

我有一个基础 class Attr(属性),它有两个派生的 classes NomAttr(标称属性)和 NumAttr(数值属性)。

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

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

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


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

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

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

伪代码 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

使用模板:

#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<int>Attribute<std::string> 或您需要的任何其他类型。

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

其实你只需要一个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;
}

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