C++ 外部常量默认构造对象

C++ 外部常量默认构造对象,c++,class,constructor,extern,C++,Class,Constructor,Extern,这是我的密码 #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的对象t,其链接是

这是我的密码

#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的对象t,其链接是外部的,其字段不能修改。创建是由构造函数完成的,没有参数,我已经提供了参数

在main中,我希望以相同的方式创建一个类型为Q的本地t对象,尽管它的链接必然就是这个文件,事实上,它的范围和持续时间只针对main

C++允许我在常量qt/中放置或不放置括号;大体上。在全局范围中,我可以在A行中放入或不放入括号,并且构造函数不会以任何方式调用

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

我的问题是:

考虑到在第//B行中不存在这种灵活性,为什么允许我灵活地将或不放在第//A行中

不管我在1中做了什么选择,我发现构造器不是由A行打印的,即使它是在B行打印的。为什么?我对此并没有什么期望。一方面,打印它是合理的,因为我们主要看到C++即使没有括号也能调用0参数构造函数。另一方面,如果是这样的话,那么我将如何进行类类型的非定义声明呢


带有extern关键字的对象声明不是定义,除非它包含显式初始值设定项。您试图使用以强制定义是朝着正确方向迈出的一步。但是,它失败了,因为这样的声明会产生语法歧义,这种歧义的解决有利于函数声明,而不是对象声明

这同样适用于您所有的声明,而不仅仅是B,正如您似乎相信的那样。我不清楚为什么您声称B行不存在这种灵活性:您可以在B行中包含或省略它。在任何一种情况下,声明都是完全有效的,除非它将声明一个函数。也就是说,这不仅仅是一种灵活性,而是一种非常剧烈的质量变化

对于B行,这个问题实际上是不存在的,因为B行没有使用extern关键字。无论是否使用显式初始值设定项,无外部行B都是对象定义。在您的情况下,保持原样仍然会触发默认构造,就像您希望的那样。这同样适用于main内部的本地声明

另一方面,行A是有问题的,因为为了强制定义,您需要一个显式的初始值设定项,但这不符合您的要求

为了在经典C++98中解决这个问题,您必须使用

extern const Q t = Q();
语法,以确保您正在创建由默认构造函数初始化的对象定义。迂腐地说,它实际上是默认构造,后面是复制构造,但这是我们在C++98中不得不接受的

<>在现代C++ C++ 11和以后,可以使用{}初始化器

将其定义为默认结构的定义。
extern const Q t{};


基于{}的语法显然不会对函数声明产生任何歧义。

Ir并不完全清楚您的要求,但是这个常量qs并不构造任何东西,它声明了一个函数。在这里和其他地方搜索最烦人的问题。我怎样才能澄清我的问题?帕伦夫妇被注释掉了。他们不会被允许的,就像你和我都提到的,他们会被允许的。在这里发布时,不要发布注释掉的代码-这只会使您更难理解您实际询问的内容,并且如果我们想编译代码,需要我们编辑代码。@NeilButterworth,我不认为标记为重复的帖子回答了OP的问题。@NeilButterworth我不知道你的链接如何回答我提出的两个问题。你是对的,可以把括号放在B行。重要的是我已经注释掉了括号,以便在下面,你知道我在说什么。以下是我的问题,重新措辞。有$2^3=8$可能的组合是省略还是放入括号,还有一个问题是代码是否编译以及输出是什么。
extern const Q t = {};