1

早些时候我问为什么这被认为是不好的:

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

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

4

5 回答 5

5

很简单,丹尼尔:

Example *e = new Example();

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

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

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

于 2009-01-19T14:28:20.413 回答
1

这个问题将有助于理解这种行为

于 2009-01-19T14:27:48.307 回答
1

嗯...好吧这个:

示例 e1();

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

这:

示例* e1 = 新示例();

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

于 2009-01-19T14:28:24.110 回答
1

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

例子:

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

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

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

于 2009-01-19T14:28:47.570 回答
0

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

Example e1(); // function prototype

看起来像一个函数声明。解析器因此理解它,因此您不能调用例如成员函数 on 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 编译器识别的关键字,并且它知道它只能在新对象的分配+构造中找到,它将生成这样做的代码。

于 2009-01-19T14:38:00.813 回答