C++ Make a generic interface
我有一个接口(这里缺少很多成员,但是请注意这个接口是强制的)。我需要5个继承自它的类,它们将具有一个值属性。所以,INS实现5个类(char、short、int、float、double)的tead,我想到了一个模板类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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; } }; |
…这样就可以工作了:
1 2 3 4 5 6 7 8 | 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,因为它是我需要的最大大小的类型。但是,我不喜欢那个解决方案。
如果您的接口上只有一个方法(getValue()),那么您只需要模板类实现。
但是,如果您想要这样的接口:
1 2 3 | std::string getValue(); int getValue(); long getValue(); |
那么您就走运了,因为您不能只根据返回类型重载函数名。或者,您可以创建包装类型。
编辑
我的意思是,如果需要GetValue返回多个类型,您可以通过多种方式使用封装所需功能的包装类,而不是将其添加到顶级接口。它可能看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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 } |
那么你的界面是
1 2 3 | public class my_interface{ virtual Wrapper getVal(); } |
您在这里的收获并不多,因为用户仍然需要调用包装器的正确子成员。如果需要,还可以将返回值表示为字符串。
请注意,使用工会时,您需要注意以下注意事项:http://en.cppreference.com/w/cpp/language/union
编辑2:你可以用模板化的返回来做这个。
1 2 | template<typename = T> const T& getVal(const T& typeToAllowMethodOverriding) const; |
我认为你最好的办法是使用/实现类似于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; } }; |
然后可以实现算术运算符:
1 2 3 | Value operator+(const Value &lhs, const Value &rhs) { //Check the internal types of lhs and rhs and perform the operation } |
您还可以将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; } }; |
它适用于所有类型,但对于字符串类型,必须对模板进行专门化。
您也可以将类"我的接口"设置为模板类:
1 2 3 4 5 6 | template<typename T> class my_interface { public: virtual T getValue() const = 0; }; |
这将为您使用的每个T类型生成一个接口和一个类。
记住,"virtual…"的意思是"在类中创建一个函数指针,我将使用它来调用正确的派生类"。它只是一个指针——所以在调用它之前,必须在返回类型上达成一致。C++没有其他语言的动态类型和反射——它必须知道在调用之前返回类型是什么。