8

我有Simpletron.cpp一个文件,一个Simpletron.h声明一个Simpletron类:

class Simpletron 
{    
public:
    Simpletron();
};

我调用Simpletron()了我的 main.cpp:

#include <iostream>
#include "Simpletron.h"

int main(int argc, char *argv[]) 
{

    Simpletron s();
    std::cin.get();
}

main 函数运行平稳,没有任何警告或错误。这是为什么?如果没有头文件可以链接到的实现,它甚至如何编译?

4

3 回答 3

25

这一行:

Simpletron s();

是一个函数原型,声明一个名为 的函数s,返回 aSimpletron并且不接受任何参数。它不会创建Simpletron名为 的实例s

现在你可能会问,为什么链接器不抱怨不存在的s()函数呢?好吧,由于您只是声明s()但从未实际调用它,因此在链接期间实际上并未在任何地方引用它,因此您不会收到链接错误。

于 2013-09-24T00:38:36.903 回答
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
于 2013-09-24T00:54:29.080 回答
5
    Simpletron s();

这是一个“恼人的解析”的经典案例;对于编译器,您不是在创建stype的变量Simpletron,而是在声明一个名为 的函数s,不接受任何参数并返回一个Simpletron对象。

这是因为这个表达式既可以解释为函数声明也可以解释为变量声明。因为要声明变量,所以有一个简单的替代方法(即,只需省略括号)标准要求将其解释为函数声明。

这可以毫无问题地通过编译阶段(编译器不需要所有方法的定义,只需要声明),并且链接器可能不会给出任何错误,因为Simpletron实际上没有创建实例,所以它永远不需要实际查找构造函数定义(尽管我认为不能保证不会出错,但特别彻底的编译器/链接器对应该能够为缺少的构造函数提供错误)。

于 2013-09-24T00:57:22.163 回答