我有Simpletron.cpp
这是空文件,Simpletron.h
声明了Simpletron
类:
class Simpletron
{
public:
Simpletron();
};
我在main.cpp中调用了Simpletron()
:
#include <iostream>
#include "Simpletron.h"
int main(int argc, char *argv[])
{
Simpletron s();
std::cin.get();
}
主要功能运行顺畅,没有任何警告或错误。这是为什么?如果没有头文件可以链接到的实现,那么如何编译甚至编译?
答案 0 :(得分:25)
这一行:
Simpletron s();
是一个函数原型,声明一个名为s
的函数,返回Simpletron
并且不带参数。它不会创建名为Simpletron
的{{1}}实例。
现在您可能会问,为什么链接器不会抱怨不存在的s
函数呢?好吧,因为你只是声明s()
但实际上从未实际调用它,所以在链接期间它实际上并没有被引用,所以你没有链接错误。
答案 1 :(得分:13)
Simpletron s();
这是函数声明,而不是对象实例化。空括号告诉编译器此函数不带参数,并按值返回类型为Simpletron
的对象,因此不会调用构造函数。正确的语法没有参数:
Simpletron s; // You will get an error on this line, as initially expected
C ++ 11增加了一个避免这种歧义的语法特性:
Simpletron s{}; // same as default-initialization
答案 2 :(得分:5)
Simpletron s();
这是“烦恼的解析”的经典案例;对于编译器,您不是要创建类型为s
的变量Simpletron
,而是声明一个名为s
的函数,不带参数并返回Simpletron
对象。 / p>
这是因为这个表达式既可以解释为函数声明,也可以解释为变量声明;因为声明变量有一个简单的替代方法(即,只是省略括号)标准要求将其解释为函数声明。
编译阶段没有问题(编译器不需要具有所有方法的定义,只需要声明),并且链接器可能不会给出任何错误,因为没有Simpletron
的实例实际上是创建的,所以它永远不需要实际查找构造函数定义(虽然我不认为保证不会给出错误,一个特别彻底的编译器/链接器无论如何,情侣应该能够为缺少的构造函数提供错误。)