早些时候我问过为什么这被认为是坏事:
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);
}
所以我有点困惑:(对不起,如果这被问了一百万次。
答案 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
,并且它知道它只能在分配+构造新对象中找到,它将生成代码来执行此操作。