条件变量声明
我来自 Python,在管理 C++ 中的类型时遇到一些问题。在Python中我可以做这样的事情:
if condition_is_true:
x=A()
else:
x=B()
在程序的其余部分我可以使用x而不关心x的类型,因为我使用具有相同名称和参数的方法和成员变量(A和B不一定有相同的基类)。 现在,在我的 C++ 代码中,类型 A 对应于
typedef map<long, C1> TP1;
,B 对应于:
typedef map<long, C2> TP2;
其中:
typedef struct C1
{
char* code;
char* descr;
int x;
...
}
和
typedef struct C2
{
char* code;
char* other;
int x;
...
}
C1 和 C2 具有相似的成员,并且在我正在谈论的代码部分中,我只需使用
我想要的 具有相同名称/类型的成员做类似的事情:
if (condition==true)
{
TP1 x;
}
else
{
TP2 x;
}
c++ 中正确的方法是什么?
提前致谢
I'm coming from Python and I have some problem with managing types in c++. In Python I can do something like this:
if condition_is_true:
x=A()
else:
x=B()
and in the rest of the program I can use x without caring about the type of x, given that I use methods and member variables with the same name and arguments (not necessary that A and B have the same base classes).
Now in my C++ code type A corresponds to
typedef map<long, C1> TP1;
and B to:
typedef map<long, C2> TP2;
where:
typedef struct C1
{
char* code;
char* descr;
int x;
...
}
and
typedef struct C2
{
char* code;
char* other;
int x;
...
}
C1 and C2 have similar members and in the part of code I'm talkin of I only have to use the ones with the same name/type
I would like to do something like:
if (condition==true)
{
TP1 x;
}
else
{
TP2 x;
}
what is the correct approach in c++?
thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果条件在编译时已知,则可以使用 std::conditional。这在通用代码中很有用。
(其中测试是虚构的;这里我们测试
T
是否是指针类型)如果直到运行时才能知道条件,则需要某种形式的动态多态性。 C++ 中此类多态性的典型实例是子类型、
boost::variant
或当紧要关头时boost::any
。您应该选择哪一个*以及如何应用它取决于您的总体设计;我们知道的还不够。*:很可能不是是
boost::any
。If the condition is known at compile-time, you can use
std::conditional
. This is useful in generic code.(where the test is made-up; here we're testing whether
T
is a pointer type or not)If the condition cannot be known until runtime, then some form of dynamic polymorphism is needed. Typical instances of such polymorphism in C++ are subtyping,
boost::variant
or when push comes to shove,boost::any
. Which one you should pick* and how you should apply it depends on your general design; we don't know enough.*: very likely not to be
boost::any
.你有几个选择。如果 C1 和 C2 都是 POD 类型,则可以使用联合,它允许访问公共初始序列:
请注意,为了保持初始序列“公共”,您确实需要更改名称,以便第二个成员 (
descr
/other
) 在该结构的两个版本中具有相同的名称。如果它们不是 POD,您可以使用继承来为您提供通用类型。
然而,C++ 并没有与 Python 著名的“鸭子类型”直接对应的东西。虽然模板提供了类型擦除(至少在某种程度上),但您最终会得到与在 Python 中所做的相反的结果。您可以允许代码处理具有共同语法的两种不同类型,而不是在处理变量时发生两种类型之间的变化。然而,这是不同的,因为它要求编译器能够在编译时(而不仅仅是运行时)解析与任何特定模板一起使用的实际类型。
如果您确实需要在运行时解析类型,那么模板可能不起作用——您可能需要使用联合或基类。
You have a couple of choices. If C1 and C2 are both POD types, you could use a union, which allows access to the common initial sequence:
Note that to keep the initial sequence "common", you really want to change the names so the second member (
descr
/other
) has the same name in both versions of the struct.If they're not PODs, you can use inheritance to give you a common type.
C++, however, doesn't have a direct counterpart to Python's famous "duck typing". While templates provide type erasure (to at least some degree), you'd end up with kind of the reverse of what you're doing in Python. Instead of the variation between the two types happening where you deal with the variable, you'd allow code to deal with two different types that had common syntax. This is different, however, in that it requires that the compiler be able to resolve the actual type being used with any particular template at compile time, not just run time.
If you really need to resolve the type at run time, then templates probably won't work -- you'll probably need to use a union or base class.
如果您确实需要两种不同的类型,最好的办法是(假设这些类相似并且具有一些相似的成员函数)有一个抽象类,例如 CBase (请参阅 http://www.cplusplus.com/doc/tutorial/polymorphism/)然后定义这个抽象类的两个子类C1和C2 。
现在您的代码可以编写如下:
如果您无法将 C1 和 C2 抽象为一个公共抽象类,那么您将需要两个不同的变量,并且
condition
的作用类似于您使用的标志稍后可以知道哪个变量已被填充以及要使用哪个结构。If you really need two different types, the best thing to do would be (assuming the classes are similar and has some similar member functions) to have an abstract class, say, CBase (see http://www.cplusplus.com/doc/tutorial/polymorphism/) and then define two subclasses C1 and C2 of this abstract class.
Now your code can be written as follows:
In case you can not abstract C1 and C2 into a common abstract class, well, then you'll need two different variables and
condition
acts like your flag using which you can know later which variable has been populated and which structure to work with.尽管可能有一些方法可以做到这一点,但正如达蒙提到的那样,它们大多很棘手且不可维护。
我建议您使用模板功能。您真正想要的是访问不同类的相同成员/函数。在模板函数中,您可以访问“通用类型”的对象,只要该类型提供您在模板中使用的操作即可。
例如,在您的情况下,您可以简单地将公共部分提取到这样的模板函数中。
Although there may be some ways to do it, they're mostly tricky and not maintainable, just as Damon mentioned.
I recommend you to use template function. What you really want is to access the same member/functions for different class. In template function, you can access the object of a "general type" as long as the type provides the operation you use in the template.
For example, in your case you can simply extract the common parts into a template function like this.
我认为你可以通过运行时多态性来做到这一点。
i think you can do it by runtime polymorphism.
为了通过公共变量使用两种不同的类型,类型
必须有一个共同的基类。因为你拥有的是两个不同的
您无法更改且没有公共基类的类型,
你需要某种鸭子打字。在C++中,只有模板使用duck
键入:一种解决方案是将所有代码移至
将条件放入单独的函数模板中,您可以将
结果,然后编写如下内容:
根据实际遵循条件的代码,这可能是
或多或少方便。
更通用的替代方法是创建类层次结构来包装
地图。这个解决方案有点冗长,但非常简单:只需定义一个基数
具有您想要的接口的类,例如:
,然后是从它派生的模板:
您的
if
然后变为:In order to use two different types through a common variable, the types
must have a common base class. Since what you have is two different
types which you can't change, and which don't have a common base class,
you need some sort of duck typing. In C++, only templates use duck
typing: one solution would be to move all of the code after the
condition into a separate function template, to which you pass the
results, and then write something like:
Depending on the code that actually follows the condition, this may be
more or less convenient.
A more general alternative is to create your class hierarchy to wrap the
maps. This solution is a bit verbose, but very easy: just define a base
class with the interface you want, say:
, and then a template which derives from it:
Your
if
then becomes:你想要做的事情在 C++ 中是不可能的。 C++ 中的变量具有在编译时定义的固定类型,并且不能在运行时更改类型。但是 C++ 确实提供了多态性(看起来像动态类型),它允许派生类型实现基类功能,但访问特定于类型的方法的唯一方法是将类型绑定到基类,如果您有一个类型绑定到派生类型,那么你只能调用该类型的实现*:
看起来
b
已经改变了类型,但它的实际类型保持不变,它始终是一个基数 *
并且只能是分配了值c1
和c2
,因为它们共享一个公共基类Base
。也可以采用另一种方式:但它需要
dynamic_cast
并且需要称为 RTTI(运行时类型信息)的东西,它为编译后的代码提供了一种检查b
b 的方法。 code> 实际上指向一个C1
类型。如果您要执行以下操作:c1
将是空指针,而不是b
。但 C1 和 C2 仍必须有一个共同的基类才能正常工作。这是不合法的:如果 C1 和 C2 相关(例如,CSquare 和 CCircle),那么公共基类就有意义。如果它们不相关(例如,CRoad 和 CFood),那么公共基类将无济于事(可以做到,但不太符合逻辑)。其他答案中已经很好地描述了前者(公共基类)。如果您需要执行后者,那么您可能需要重新思考代码的结构如何允许您执行前者。
如果您可以扩展您想要使用
x
执行的操作,将会有所帮助。既然x
是一个容器,那么你只想做容器相关的操作吗?示例:
What you're trying to do is not possible in C++. Variables in C++ have a fixed type which is defined at compile time and they can't change type at run time. But C++ does provide polymorphism (which looks like dynamic types) which allows derived types to implement base class functionality, but the only way to access type specific methods is to have a type bound to the base class, if you have a type bound to the derived type then you can only call that type's implementation*:
It looks like
b
has changed type, but it's actual type has remained the same, it is always aBase *
and it can only be assigned the valuec1
andc2
because they share a common base classBase
. It is possible to go the other way:but it requires the
dynamic_cast
and that requires something called RTTI (Run-Time Type Information) which provides the compiled code a way to check thatb
is actually pointing to aC1
type. If you were to do the following:c1
would be the null pointer, notb
. But C1 and C2 must still have a common base class for this to work. This is not legal:If C1 and C2 are related (say, CSquare and CCircle) then a common base class makes sense. If they are not related (say, CRoad and CFood) then a common base class won't help (it can be done, but it's not very logical). Doing the former (common base class) has been well described in the other answers. If you need to do the latter, then you may need to re-think how the code is structured to allow you to do the former.
It would help if you could expand on what you want to do with
x
. Sincex
is a container, do you just want to do container related operations?Example: