我有一个接口(缺少很多成员,但请注意这个接口是必需的)。我需要继承5个类,它们将具有_ 值属性。所以,ins \ 实现了5个类(用于char,short,int,float,double),我想到了一个模板类:
class my_interface
{
public:
virtual [various_types] getValue() const = 0;
};
template<typename T>
class my_class : public my_interface
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
virtual T getValue() const { return _value; }
};
...这样的东西可以起作用:
void my_function()
{
my_inteface* a = new my_class<char>(42);
my_interace* b = new my_class<short>(21);
int result;
result = a->getValue() + b->getValue();
}
但我不明白我该怎么做。看来你无法在界面纯虚拟上制作模板。对我来说,唯一可行的方法是让 getValue()始终返回一个double,因为它是我需要的最大尺寸类型。但是,我不喜欢这个解决方案。
答案 0 :(得分:1)
如果您的接口只有一个方法(getValue()),那么您只需要模板类实现。
但是如果你想要这样的界面:
std::string getValue();
int getValue();
long getValue();
然后你运气不好,因为你不能只根据返回类型重载函数名。或者,您可以创建包装类型。
修改强>
通过包装器类型我的意思是,如果需要getValue来返回多个类型,您可以使用封装类以多种方式执行此操作,该封装类封装了您所需的功能,而不是将其添加到顶级接口。它可能看起来像这样:
enum ValType{
INT, CHAR, STR, DEQUE
};
class Wrapper{
private:
union S{
int intVal;
char charVal;
std::string stringVal;
std::deque dequeVal;
~S() {}
} theVal;
ValType heldType;
public:
void setVal(int value){ heldType = INT; theVal.intVal = value; }
void setVal(char value){ heldType = CHAR; theVal.charVal = value; }
// ... and so on
int getIntVal() const {
if(heldType!=INT)
throw std::runtime_error("Cop on");
return theVal.int;
}
// and so on
}
然后你的界面是
public class my_interface{
virtual Wrapper getVal();
}
由于用户仍需要调用Wrapper的正确子成员,因此您在这里并没有获得太多收益。 如果需要,您也可以将返回值表示为字符串。
请注意,使用工会时,您需要注意警告: http://en.cppreference.com/w/cpp/language/union
编辑2: 你可以用模板化的回报来做到这一点
template<typename = T>
const T& getVal(const T& typeToAllowMethodOverriding) const;
答案 1 :(得分:0)
请记住,'virtual ...'表示“在类中创建一个函数指针,用于调用正确的派生类”。它只是 一个指针 - 所以你必须在调用之前就返回类型达成一致。 C ++没有动态类型和其他语言的反映 - 在调用之前必须知道返回类型是什么。
答案 2 :(得分:0)
你也可以让my_interface类成为模板类:
template<typename T>
class my_interface
{
public:
virtual T getValue() const = 0;
};
这将为您使用的每个类型T生成一个接口和一个类。
答案 3 :(得分:0)
template<typename U>
class my_interface
{
public:
virtual U getValue() const = 0;
};
template<typename T>
class my_class : public my_interface<T>
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
T getValue() const { return _value; }
};
它适用于所有类型,但对于字符串类型,您必须对模板进行专门化
答案 4 :(得分:0)
我认为你最好的方法是使用/实现像boost::variant
这样的东西。
typedef boost::variant<char, short, int, float, double> Value;
class my_interface
{
public:
virtual Value getValue() const = 0;
};
template<typename T>
class my_class : public my_interface
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
virtual Value getValue() const { return _value; }
};
然后你可以实现算术运算符:
Value operator+(const Value &lhs, const Value &rhs) {
//Check the internal types of lhs and rhs and perform the operation
}
您还可以将boost::variant
打包到另一个类中,以便为基本类型提供转换运算符。