C ++类默认构造函数

时间:2009-01-19 14:22:52

标签: c++ constructor class default

早些时候我问过为什么这被认为是坏事:

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);
}

现在,我知道它正在创建一个函数原型而不是返回一个类型的示例。我仍然不明白为什么它可以在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);
}

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

5 个答案:

答案 0 :(得分:5)

很容易,丹尼尔:

Example *e = new Example();

这看起来不像是一个名为“Example”的函数,是吗?函数具有返回值,名称和参数。以上怎么样?

  

示例e1(); //这个有用吗

是的,因为你不会在任何地方创建Example的任何实例。你只需告诉代码在某个地方有一个在周围命名空间中定义的函数,你可能想调用那个函数。是的,为了返回Example的对象,确实会生成一个实例。但这并不意味着在那一点上制作了一个实例。而是在调用它时在函数中创建一个实例。

答案 1 :(得分:1)

question将有助于理解此行为

答案 2 :(得分:1)

嗯......好吧:

示例e1();

不起作用。您可能认为它确实存在,或者某些编译器正在接受它,但它不会创建一个名为e1的Example实例,它只是声明了一个函数原型。删除括号,它会做你想要的。

此:

示例* e1 = new Example();

无法工作,因为构造函数是私有的。如果你将构造函数设为public,它将在堆上创建对象,e1将是指向该对象的指针。完成后,您将需要删除该对象。

答案 3 :(得分:1)

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

示例:

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

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

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

答案 4 :(得分:0)

我认为你应该区分'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,并且它知道它只能在分配+构造新对象中找到,它将生成代码来执行此操作。