[英]c++ dynamic return type
I'm not sure if this is a thing (to be honest I want to say that it is not), but I was wondering if there is a way to write a c++ function so that it can choose which type of object to return. 我不确定这是否是一个东西(说实话我想说它不是),但我想知道是否有办法编写一个c ++函数,以便它可以选择返回哪种类型的对象。
For example, I have a base class ( A
) that has 3 child classes ( Aa
, Ab
, Ac
). 例如,我有一个基类(
A
),它有3个子类( Aa
, Ab
, Ac
)。 In a factory( F
) class I have a std::map<UINT, A*>
that holds a number of the child classes based on a UINT id
. 在工厂(
F
)类中,我有一个std::map<UINT, A*>
,它根据UINT id
保存了许多子类。 My goal is to write a function that can build and return the correct object when I pass in an id value. 我的目标是编写一个函数,当我传入一个id值时,它可以构建并返回正确的对象。
I'll probably end up returning pointers and cloning the data that they point to, but I was just curious as to whether or not the aforementioned was actually possible. 我可能最终会返回指针并克隆他们指向的数据,但我只是好奇上述内容是否真的可行。
Thanks! 谢谢!
C++ being statically typed, the return type of a function must be known at compile time. C ++是静态类型的,函数的返回类型必须在编译时知道。 From here arises the question:
从这里出现了一个问题:
F
(== it only depends on constant expression
values) F
每个调用站点上静态地知道预期的返回类型(==它仅取决于constant expression
值) For case #1, a function template for F
would be a good approach. 对于情况#1,
F
的函数模板将是一种很好的方法。
But in your case, it seems you are facing #2 (because you want to return a type depending on ID
that we can assume is not a constant expression). 但在你的情况下,你似乎面临#2(因为你想要返回一个类型,取决于我们可以假设不是常量表达式的
ID
)。
Because of the static typing, if you are to write a function (assuming you do not overload it, because it seems your input parameters are always the same), it will have a single and well-defined return type. 因为静态类型的,如果你是编写一个函数(假设你不超载,因为它似乎你的输入参数都是一样的),这将有一个单一的和明确的返回类型。 Basically, you do not have a syntax to say that your factory
F
will return either an Aa
Ab
or Ac
(and that is a very good thing, with regard to static typing and all the compiler verifications it enables ; ) 基本上,你没有语法说你的工厂
F
将返回Aa
Ab
或Ac
(这是一个非常好的事情,关于静态类型和它启用的所有编译器验证;)
With that being said, you have a few approaches to type erasure , that will allow you to return an instance of a variant type hidden behind a common single type. 话虽如此,您可以使用一些方法来键入擦除 ,这将允许您返回隐藏在常见单一类型后面的变体类型的实例。
The obvious one is the pointer-to-derived to pointer-to-base conversion. 显而易见的是指针到指针到基础的转换。 It is particularly usefull if you plan to use the returned object mainly through its
A
interface (ie, you will call the virtual functions defined on A
). 如果您计划主要通过其
A
接口使用返回的对象(即,您将调用在A
定义的虚函数),这将特别有用。
A* F(ID aId)
This A*
could point to any type deriving from A
. 这个
A*
可以指向任何来自A
类型。 From here, you could call every function defined on A
public interface on the returned pointer. 从这里,您可以在返回的指针上调用
A
公共接口上定义的每个函数。 Of course, if you wanted to call an operation that is only available on a subclass, you would need to know what is the exact type on call site,and then cast the pointer to a pointer-to-derived before being able to call the operation. 当然,如果你想调用一个只在子类上可用的操作,你需要知道调用站点上的确切类型是什么,然后将指针强制转换为指向派生的指针,然后才能调用操作。
A possible alternative, if you'd rather avoid dynamic memory, could be boost::variant
. 如果您宁愿避免动态内存,可能的替代方案可能是
boost::variant
。 At the cost of having to explicitly list all the possible types the function could return. 以必须明确列出函数可能返回的所有可能类型为代价。
boost::variant<Aa, Ab, Ac> F(ID aId);
You can take a look at the tutorial for a quick introduction to the syntax and features. 您可以查看本教程 ,快速了解语法和功能。
Sure, something like this: 当然,这样的事情:
class MyMapClass
{
public:
template< class ExactType > ExactType * getValue(UINT key)
{
return dynamic_cast<ExactType*>(_myMap.at(key));
}
BaseType * at(UINT key)
{
return _myMap.at(key);
}
private:
std::map<UINT, BaseType*> _myMap;
}
However, since you are storing the pointers to base types, you can as well return them as is, and rely on the caller to make a specific cast, if that goes well with your application's architecture. 但是,由于您将指针存储到基类型,因此您也可以按原样返回它们,并依赖调用者进行特定的转换,如果这与您的应用程序的体系结构相符合。
Unfortunately, you can not do it fully automatically. 不幸的是,你无法完全自动完成。 Sooner or later you will have to determine the exact class that hides behind the base class pointer, and make a cast.
迟早你必须确定隐藏在基类指针后面的确切类,并进行强制转换。 With the template solution it is done "sooner":
使用模板解决方案,它可以“更快”完成:
MyDerivedType * value = myMapClassInstance.getValue<MyDerivedType>(1);
If you prefer to return the base pointer, it is done "later": 如果您希望返回基指针,则会“稍后”完成:
BaseType * value = myMapClassInstance.at(1);
MyDerivedType * exactValue = dynamic_cast<MyDerivedType*>(value);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.