1

我在 Google 上找不到任何关于此的信息,在以下示例中:

    #include <iostream>

    class Default
    {
    public:
      void Print()
      {
        std::cout << "This is a message\n";
      }
    };

    template <class C = Default>
    class Template
    {
    public:
      static void Test()
      {
        Default oDefault();
      }
    };

    int main()
    {
      return 0;
    }

代码无法编译并出现以下错误:

在静态成员函数'static void Template::Test()'中:19:22:错误:没有 -std=c++0x 或 -std=gnu++0x 的函数模板中不能使用默认模板参数

问题是它不喜欢出现在该行的括号,我不明白为什么。如果我删除括号代码编译就好了。此外,如果我删除模板声明(第 13 行),它也编译得很好。这是一个错误还是关于这种情况的某个地方有什么规则?

我正在使用 g++4.6.1(gcc 版本 4.6.1(Ubuntu/Linaro 4.6.1-9ubuntu3))

4

2 回答 2

2

将其更改为:

 Default oDefault = Default();  // Version 1

虽然你可以使用:

 Default oDefault;              // Version 2

这有一个稍微不同的含义。

  • 版本 1:使 POD 成员初始化为零(在某些情况下)。
  • 版本 2:导致 POD 成员未初始化(在某些情况下)。

通过版本一看起来它调用了额外的副本构造,但情况并非如此(在大多数编译器中),因为额外的副本将被编译器忽略,并且会发生简单的正常(零初始化)构造。

您应该更喜欢零初始化而不是默认(通常),好像类(或任何成员类型)没有用户定义的构造函数(如默认),那么区别在于默认初始化使 POD 成员未定义而零初始化离开POD 成员初始化为零。现在你可能会认为我的班级没有成员,所以没关系。但是如果你修改类会发生什么,你要去查找所有实例并更新它们吗?最好使用版本一并让编译器做正确的事情。

有关所有令人兴奋的细节,请参阅:

您的初始版本不起作用的原因是它实际上是函数的前向声明。这是由 C++ 的复杂语法引起的,这只是您需要记住的规则之一。您可以将其视为“最令人烦恼的解析”。

于 2012-03-19T04:57:52.450 回答
1
Default oDefault();

编译器将此视为函数声明,而不是创建对象。
它声明了一个oDefault()不带参数并返回一个Default对象的函数。

将其更改为:

Default oDefault;
于 2012-03-19T04:07:24.243 回答