C++ 在不知道底层类型的情况下,如何从模板化父类获取值?
为了便于说明,给出了这些定义和一些代码:C++ 在不知道底层类型的情况下,如何从模板化父类获取值?,c++,templates,polymorphism,C++,Templates,Polymorphism,为了便于说明,给出了这些定义和一些代码: class Child { private: std::string name; public: Child(const std::string & name) name(name) { } } template<typename T> class Parent : public Child { private: T data; public Parent(cons
class Child
{
private:
std::string name;
public:
Child(const std::string & name) name(name)
{ }
}
template<typename T>
class Parent : public Child
{
private:
T data;
public Parent(const std::string & name, const T & data) : Child(name), data(data)
{ }
inline GetData() const
{
return this->data;
}
}
std::vector<std::unique_ptr<Child>> values;
values.emplace_back(std::make_unique<Parent<int>>("value a", 4));
values.emplace_back(std::make_unique<Parent<std::string>>("value b", "test"));
for (const auto & v : values)
{
// I want to access the int and string here!
}
类子类
{
私人:
std::字符串名;
公众:
子(const std::string&name)名称(name)
{ }
}
模板
父类:公共子类
{
私人:
T数据;
公共父(const std::string&name,const T&data):子(name),数据(data)
{ }
内联GetData()常量
{
返回此->数据;
}
}
std::向量值;
值。向后放置(标准::使值唯一(“值a”,4));
值。向后放置(标准::使值唯一(“值b”、“测试”);
用于(常量自动和v:值)
{
//我想在这里访问int和string!
}
如何从这里的基类确定父类中使用的类型
我正在处理的具体场景实际上是,我有一堆SqlParameterBase
类,其中包含有关存储过程的SQL参数的信息,还有一个SqlParameter
模板,该模板应该包含在std::vector
中,并传递到表示存储过程的类中配置,以便可以调用它
但这里的基本问题是,我需要访问底层数据,我希望避免在基类中定义void*
,以包含指向数据的指针。我希望它尽可能的安全
我对解决此问题的其他设计或方法也持开放态度,因此如果您觉得更好,请随意提出完全不同的建议。尝试此程序(对于以下问题:如何从这里的基类确定父类中使用的类型?):
输出打印类型。。
但为了看起来更好,还需要做更多的工作
value a of type:i
value b of type:NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
这里“i”表示第一行中的整数
第二个有“基本字符串”。但是周围有一些垃圾
我之所以发布这篇文章,是因为它可能会引发更好的想法
为修改的代码添加了注释
//g++ 5.4.0
#include <iostream>
#include <string>
#include <vector>
#include <memory>
//CREATED ANOTHER VARIABLE AND FUNCTION FOR TYPENAME.
//MODIFIED CONSTRUCTOR ACCORDINGLY.
class Child
{
private:
std::string name;
std::string tyName;
public:
Child(const std::string & name,const std::string &tyname):name(name), tyName (tyname)
{ }
std::string getName()
{
return name;
}
std::string getTypeName()
{
return tyName;
}
};
//MODIFIED CONSTRUCTOR TO PASS THE TYPENAME TO PARENT CLASS.
template<typename T>
class Parent : public Child
{
private:
T data;
public:
Parent(const std::string & name, const T & data) : Child(name,typeid(data).name()), data(data)
{ }
inline T GetData() const
{
return this->data;
}
};
int main()
{
std::vector<std::unique_ptr<Child>> values;
values.emplace_back(std::make_unique<Parent<int>>("value a", 4));
values.emplace_back(std::make_unique<Parent<std::string>>("value b", "test"));
//GET THE POINTER OF YOUR BASE CLASS.
//PRINT THE TYPE NAME.
for (const auto & v : values)
{
Child *p = dynamic_cast<Child*>(v.get());
std::cout<<p->getName()<<" of type:"<<p->getTypeName()<<std::endl;
}
return 0;
}
//g++5.4.0
#包括
#包括
#包括
#包括
//为TYPENAME创建了另一个变量和函数。
//相应地修改了构造函数。
班童
{
私人:
std::字符串名;
std::字符串tyName;
公众:
子(const std::string&name,const std::string&tyname):name(name),tyname(tyname)
{ }
std::string getName()
{
返回名称;
}
std::string getTypeName()
{
返回tyName;
}
};
//修改了构造函数以将TYPENAME传递给父类。
模板
父类:公共子类
{
私人:
T数据;
公众:
父(const std::string&name,const T&data):子(name,typeid(data).name()),数据(data)
{ }
内联T GetData()常量
{
返回此->数据;
}
};
int main()
{
std::向量值;
值。向后放置(标准::使值唯一(“值a”,4));
值。向后放置(标准::使值唯一(“值b”、“测试”);
//获取基类的指针。
//打印类型名称。
用于(常量自动和v:值)
{
Child*p=dynamic_cast(v.get());
std::cout您需要仅存在于派生类型中的子承诺功能(返回类型化数据)。在继承下,这是抽象功能。因此,一组推测性虚拟访问器。这里实际上不需要上传
我会说,如果你不希望Child承诺它返回什么,只是它返回了一些东西,那么看起来你的接口太宽了,你把接口放在使用接口的代码中,比如说用推测性的强制转换等等
可以通过在Child中定义的接口与一组Child进行接口,或者它们具有一些特殊功能,仅在派生中可用,并且必须以这种方式说话
作为Wee补充,您可以考虑一个“代码> STD::vector < /Cord>,而不是完全地修改容器中的类型信息:STD::变体是C++ 17 OFC,所以可能不适合,但是有第三方实现-Boost变体等。
您需要<代码> DyjiCaseCase,但是您真正想要的是一个变体类型。是的,我知道。我需要对父类型进行动态转换。问题是,如果不以硬编码的方式测试每个类型,我无法确定转换到哪个类型。最后,我基本上需要能够确定数据的大小,比如向量中的元素数或字符串的长度;这些成员函数会发生变化基于类型。我考虑了一个模板,只是假设T::size存在,但如果函数的行为在不同类型之间定义不同,则可能会有风险。如果需要确定数据的“大小”,那么添加virtual std::size\u T size()怎么样const=0;
toChild
?@aschepler在将我的评论发布到下面的答案之前错过了您的评论。这似乎是最简单的方法,但缺点是我必须为我想要支持的每种数据类型创建类。我可以问一下,您打算对其中的数据做些什么吗?为什么不能在response下这样做家长的责任感?我问的主要是好奇。你说的是抽象功能,这让我思考。使用虚拟大小\u t GetSize()是否合适=0
在我的父类中,然后在专门用于支持的支持数据的多个子类中实现它?例如,我将有一个StringChild
和一个IntChild
,每个都将实现自己获取数据和数据大小的方法。然后我将在循环中切换,并使用枚举跟踪data类型,然后在需要获取数据时动态强制转换。似乎有很多代码,但它使我的界面更窄。经过一些阅读和修改后,std::variant
实际上非常适合我的需要。我已将我的功能缩减为一组支持