Code:
#include <iostream>
#include<map>
using namespace std;
class MyClass {
public:
class MyFieldInterface
{
public:
int m_Size;
~MyFieldInterface() = default;
};
template <typename T>
class MyField : public MyFieldInterface {
public:
MyField(T val) {m_Value = val;}
T m_Value;
};
template <typename T>
MyField<T>* getType(int type, T val) {
if (type == 0) return new MyField<int>(val);
if (type == 1) return new MyField<double>(val);
if (type == 2) return new MyField<char>(val);
}
map<string, MyFieldInterface* > fields;
};
int main()
{
MyClass obj;
obj.fields["a"] = obj.getType<int>(0, 1);
obj.fields["b"] = obj.getType<double>(1, 1.1);
obj.fields["c"] = obj.getType<char>(2, 'a');
return 0;
}
问题:
我希望std::map
保存任何值类型,因此我创建了一个具有动态继承的模板类。 我已经在MyClass
中定义了模板类,因为我不希望它的定义暴露给用户。使用getType
函数,我将创建一个具有给定类型的新对象,该对象将存储在地图中。
使用上述方法,我得到以下错误,我无法使用上述方法成功。
main.cpp: In instantiation of ‘MyClass::MyField<T>* MyClass::getType(int, T) [with T = int]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',45)">main.cpp:45:44</span>: required from here
main.cpp:34:53: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
if (type == 1) return new MyField<double>(val);
^
main.cpp:35:51: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
if (type == 2) return new MyField<char>(val);
^
main.cpp: In instantiation of ‘MyClass::MyField<T>* MyClass::getType(int, T) [with T = double]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',46)">main.cpp:46:49</span>: required from here
main.cpp:33:50: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
if (type == 0) return new MyField<int>(val);
^
main.cpp:35:51: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
if (type == 2) return new MyField<char>(val);
^
main.cpp: In instantiation of ‘MyClass::MyField<T>* MyClass::getType(int, T) [with T = char]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',47)">main.cpp:47:47</span>: required from here
main.cpp:33:50: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
if (type == 0) return new MyField<int>(val);
^
main.cpp:34:53: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
if (type == 1) return new MyField<double>(val);
^
不能使用运行时参数在多个类型之间进行选择。您需要决定在编译时返回哪种类型。但这正是模板的用途,所以你可以简单地做:
template <typename T>
MyField<T>* getType(T val) {
return new MyField<T>(val);
}
然后像这样使用函数:
obj.fields["a"] = obj.getType(1);
obj.fields["b"] = obj.getType(1.1);
obj.fields["c"] = obj.getType('a');
请注意,您不需要在调用站点指定T
,因为这可以从函数参数中推导出来。
当然,您需要跟踪地图中每个键分别引用的类型。
这是一个演示。
此外,此函数的实现方式,名称getType
令人困惑,因为您实际上并没有在此处返回类型。也许更好的名字是getAnyPointer
.