【问题标题】:C++ Classes default constructorC++ 类的默认构造函数
【发布时间】:2009-01-19 14:22:52
【问题描述】:

之前我问过为什么这被认为是不好的:

class Example
{
 public: 
  Example(void);
  ~Example(void);
  void f() {}
}

int main(void)
{
 Example ex(); // <<<<<< what is it called to call it like this?

 return(0);
}

现在,我知道它正在创建一个函数原型,而不是返回一个类型 Example。我仍然不明白为什么它会在 g++ 和 MS VC++ 中工作。

我的下一个问题是使用上述方法,这个调用是否有效?

int main(void)
{
 Example *e = new Example();

 return(0);
}

?那和简单地调用 Example e() 有什么区别???就像我知道它是一个函数原型一样,但似乎有些编译器会原谅它并允许它调用默认构造函数?我也试过这个:

class Example
{
 private:
  Example();

 public:
  ~Example();
};

int main(void)
{
 Example e1(); // this works
 Example *e1 = new Example(); // this doesn't

 return(0);
}

所以我有点困惑:(对不起,如果这被问了一百万次。

【问题讨论】:

  • 这与在堆栈中分配内存有关,而不是与默认构造函数有关

标签: c++ constructor class default


【解决方案1】:

这很简单,丹尼尔:

Example *e = new Example();

这看起来不像是一个名为“Example”的函数,是吗?函数具有返回值、名称和参数。上面的内容如何适应?

示例 e1(); // 这行得通

是的,因为您不会在任何地方创建Example 的任何实例。您只需告诉代码在某处周围的命名空间中定义了一个函数,并且您可能想要调用该函数。是的,为了返回 Example 的对象,确实会创建一个实例。但这并不意味着此时会创建一个实例。相反,当您调用它时,会在函数中创建一个实例。

【讨论】:

  • "示例 e1();"也没有返回值,但它仍然看起来像一个函数。我宁愿说 =-sign 和 new 关键字清楚地表明这是一个分配 + 构造函数调用,其结果存储在一个新声明的指针变量中
  • xtoly。示例 e1();有一个返回类型,它是那里的“示例”:)
  • 快 5 年过去了……我正在寻找一个稍微不同的主题,但这是对这个问题的一个很好的简单答案;但是我一直把它读成讽刺,我花了一段时间才理解。对于像我这样可能很慢的其他人:) 第一行是创建指向“示例”对象的指针并调用默认构造函数,而第二行是日常函数原型。
【解决方案2】:

这个question 将有助于理解这种行为

【讨论】:

  • 嘿,谢谢。所以我想这是“令人烦恼的解析”问题。是的,太棒了,我一直使用 Example e();并且从未遇到过 MS VC++(VS 2005)和 gnu g++(不记得版本)的问题。所以这对我来说是全新的......你猜你每天都会学到一些新东西。
【解决方案3】:

嗯...好吧:

示例 e1();

不起作用。你可能认为是这样,或者某些编译器正在接受它,但它并没有创建一个名为 e1 的 Example 实例,它只是声明了一个函数原型。去掉括号,它就会做你想做的事。

这个:

示例* e1 = new Example();

不会工作,因为构造函数是私有的。如果您将构造函数设为公共,它将在堆上创建对象,并且 e1 将是指向该对象的指针。完成后,您需要删除该对象。

【讨论】:

    【解决方案4】:

    对于第一个问题,“new Example()”是否有效。是的,这是完全合法的 C++ 代码。虽然为了完全正确,您需要在从 main() 返回之前删除对象,否则会导致内存泄漏。

    例子:

    int main(void)
    {
     Example *e = new Example();
     delete e;
     return(0);
    }
    

    最后一个问题。 “示例 e1();”行是有效的,因为它声明了一个函数原型。这实际上并不会导致机器代码被执行(可能是堆栈空间)。简单的说,有一个没有参数的函数原型,返回一个Example类型。

    第二行虽然肯定会失败。此时,您正在尝试实际执行 Example 的构造函数。这是不合法的,因为函数的可访问性是私有的,因此会出现编译器错误。

    【讨论】:

      【解决方案5】:

      我认为您应该区分“this parses”、“this compiles”、“this links”和“this works”,并尝试自己像 C++ 解析器/编译器/链接器一样思考以查看第一个示例

      Example e1(); // function prototype
      

      看起来像一个函数声明。解析器这样理解它,所以你不能调用例如e1 上的成员函数。编译器将生成一个引用某个函数的符号(它还没有看到),但由于该函数没有被使用,它不会抱怨。如果添加此代码,它将:

      e1.f();// since e1 is a function, it has no member 'f' => compiler error
      

      (作为旁注:这段代码也将编译:

      int a_function_prototype(int); // another prototype.
      e1(); // should work!
      a_function_prototype(5);
      

      但编译器完成后,链接器会开始寻找实际的函数体,但不会找到。)

      现在既然行了

      Example* e = new Example();
      

      包含一个关键字new编译器识别,并且它知道它只能在新对象的分配+构造中找到,它会生成这样做的代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-15
        • 1970-01-01
        • 1970-01-01
        • 2020-05-14
        • 2014-07-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多