我有一个基类Attr
(属性),它有两个派生类NomAttr
(标称属性)和NumAttr
(数字属性)。
每个成员都有一个name
成员,它始终是字符串类型。
但是,他们的value
成员有所不同:对于NomAttr
,我想获得其value
string
类型,但对于NumAttr
,我想要得到value
double
类型的Attr
。
虚函数不允许不同的返回类型,所以我有点卡在这里。 (最初我绘制下面的UML来模拟我的意图。)
很多人要我展示真正的问题。这是一个全球视图:
这是一名机器学习者。 DataSet
是数据集中实例的一部分:
Ins
由Ins
(实例)列表组成
Attr
由Attr
列表组成,Attr
的计数和每个{{1}}的类型在运行时是已知的,从用户提供的数据文件中解析用命令行参数。
你走了:
答案 0 :(得分: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<int>
和Attribute<std::string>
或您需要的任何其他类型。
编辑:如果在编译时不知道类型,这将不起作用,请参阅@MarkB答案。
答案 1 :(得分:2)
因此,根据您的更新,我认为您根本不需要任何继承来处理您的attr。相反,让基础Attr
直接包含值boost::variant<double, std::string>
,并且因为您知道它将是什么类型,您可以简单地从每个属性的变体中获取正确的类型。
答案 2 :(得分:0)
实际上你只需要一个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;
}
答案 3 :(得分:-1)
使用像其他用户建议的模板,或者不是返回值,而是传递要通过引用设置的值。
Psuedo Code 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