2017-01-27 28 views
0

这里是我的代码的extern const的默认构造的对象

#include <iostream> 
using namespace std; 

class Q 
{ 
public: 
    Q() { cout << "constructor" << endl; } 
}; 

extern const Q t/*()*/; //A 
const Q s/*()*/; //B 

int main() 
{ 
    const Q t/*()*/; 
} 

我希望行标有“A”的意思,我创建Q型,其联动是外部的对象吨,其字段不能被修改。创建是由没有参数的构造函数完成的,我已经提供了这个参数。

在我看来,我认为类型Q的本地t对象是以相同的方式创建的,虽然它的链接必然只是这个文件,事实上,它的作用域和持续时间只是主要的。

C++允许我在const Q t/() /中放置或不放置圆括号。主要。在全局范围内,在A行中,我可以放或不放括号,也不会调用构造函数。

在B行中,我只允许不放置括号,否则编译器会困惑,如果我定义的函数原型。

我的问题是:

  1. 为什么我允许灵活地把()或者不符合// A,考虑到在行// B这种灵活性不存在?

  2. 不管我在1中的选择如何,我发现“构造函数”不是由行A打印,即使它是在行B中打印。为什么?我对此没有什么期望。一方面,打印它是合理的,因为我们认为C++可以理解即使没有括号也可以调用0参数构造函数。另一方面,如果是这种情况,那么我将如何做一个类定义的非定义声明?

+0

Ir的问题并不完全清楚,但这个'const Q s()'不构造任何东西,它声明了一个函数。在这里和其他地方搜索“最令人头疼的解析”。 –

+0

@NeilButterworth我如何澄清我在问什么?这些parens被注释掉了。他们不会被允许,因为你和我都注意到了。 – Jeff

+0

他们_将被允许。在这里发布时,_don't_发表了注释掉的代码 - 这只会让你很难理解你实际询问的内容,并且如果我们想编译它,就要求我们编辑代码。 –

回答

0

一个目的声明与extern关键字是不是定义,除非它包括一个显式的初始化。您尝试使用()来强制定义是朝着正确方向迈出的一步。但是,它失败了,因为()的这种声明会产生语法歧义,这会被解析为支持函数声明,而不是对象声明。

这同样适用于您的所有声明,而不仅仅是B,因为您似乎相信。为什么你声称B线的“这种灵活性不存在”并不清楚:你可以在B行中包含()或省略它。在任何一种情况下,声明都是完全有效的,除了()它将声明一个函数。 (即,它不仅仅是“灵活性”,而是一个非常剧烈的质变)。

对于B行,问题确实不存在,因为B行不使用关键字extern。没有extern B行是一个对象定义无论你是否使用显式初始化。在你的情况下,保持原样(没有())仍会触发默认构造,就像你想要的一样。 main内的本地声明也是如此。

另一方面,行A是有问题的,因为为了强制定义你需要一个明确的初始值设定项,但是()不会做你想做的事。

为了解决这个问题,在“经典” C++ 98,你将被迫使用

extern const Q t = Q(); 

语法,以确保您所创建的默认构造函数初始化的对象定义。 (迂回地说,它实际上是默认构建,然后是复制构造,但这是我们必须在C++ 98中生活的东西)。

在现代C++(C++ 11及更高版本),你可以通过使用{}初始化它做成一个定义(默认建)

extern const Q t{}; 

extern const Q t = {}; 

{}基由于显而易见的原因,语法不会在函数声明中产生任何含糊之处。