6

在 C# 4.0 中,您可以使用“动态”关键字作为直到运行时才知道的类型的占位符。在某些极端情况下,这是非常有用的行为。是否可以在 C++ 中模拟类似的东西,可能使用 C++0x 功能或 RTTI?

4

6 回答 6

4

并不真地。您可以获得的最接近的是 a void *,但您仍然需要将其转换为适当的类型才能使用它。

更新:

基本上,试图构建一个可以编译为 C++ 的鸭式 DSL。

你至少可以通过两种方式来解决这个问题:

基于联合的变体

struct MyType {
  enum { NUMBER, STRING /* etc */ } type;
  union {
    double number;
    string str;
  };
};

多态类层次结构

class MyType {
public:
  /* define pure virtual operations common to all types */
};

class MyNumber : public MyType {
private:
  double number;
public:
  /* implement operations for this type */
};
于 2010-11-12T02:56:09.363 回答
4

C# 的dynamic功能高度依赖于 .NET 的内置反射功能。由于标准 C++ 几乎不提供反射支持,因此您无法获得类似的行为。RTTI 将允许您安全地向下转换指针,但仅此而已。您距离枚举字段和方法并动态调用它们还有很长的路要走。

于 2010-11-12T03:03:33.597 回答
2

正如其他人已经说过的那样,这在一般情况下是不可能的,但我认为看看为什么不这样做会很有帮助。

问题有两个层次,句法层次和语义层次。

在句法级别上,您有以下代码:

dynamic d = /* something */;
d.Foo(bar); // Foo is unknown at compile time

在 .NETdynamic中是一个编译器功能,它所做的不是生成函数调用,而是创建一个调用站点,其中包含函数名称和参数类型(用于重载)。这意味着如果你想支持动态,你必须修改编译器。确实,模板元编程允许做类似的事情,但 TMP 本质上是在编译时完成的,因此不能胜任支持运行时调用的工作。

如果您对语法不熟悉,那么您可以支持以下内容:

dynamic d = /* something */;
d.invoke("Foo", bar);

在语义层面 正如@Trillian(酷用户名BTW)所说,动态依赖于反射,这并不完全正确,您可以指定如何dynamic实现,并且CLR类型的默认值是反射,因此绑定到的类型dynamic变量必须支持某种运行时检查(例如 COM 的IDispatch)。这不适用于 C++ 中的一般情况,但如果您可以将支持范围缩小到仅支持(已知)检查类型的类型,您可以dynamic在 C++ 中实现(没有上述语法)。

于 2010-11-13T20:02:55.260 回答
0

这是不可能的。需要在编译时知道对象大小,因此堆栈指针可以移动适当的字节数。如果您不声明类型,那么编译器将不知道大小。C# 通过使所有对象成为指针来解决这个问题。

于 2010-11-12T03:08:28.650 回答
0

github 上的这个示例提供了一种可能的实现,具体取决于您的功能复杂性。

template <typename X, typename Y>
auto add(X x, Y y) -> decltype(x + y) {
  return x + y;
}
add(1, 2); // == 3
add(1, 2.0); // == 3.0
add(1.5, 1.5); // == 3.0
于 2020-02-25T16:44:27.970 回答
-1

我想不出一个可能的代码路径,其中值的类型实际上一直到运行时都是未知的。即使您将两个模块链接在一起(动态地,在运行时),它们都已经编译,并且它们可以返回的类型也完全确定,并且实际上编码为库公开的符号的错位名称。

但是,您可以推迟对类型的了解,直到必须实际编译代码。在 C++0x 中,有一个auto关键字,它从用于初始化变量的表达式中提供类型推断,而在当前的 C++ 中,您可以使用模板,如下所示:

template<typename T>
T square(const T& someArg){
   return T*T;
}

编辑:根据您对问题的评论,您可能没有类型未知的情况。更有可能的是,该类型仅限于少数(预定义)类型之一。为此,您可以使用union类型,最好使用boost::variant

于 2010-11-12T03:06:40.163 回答