如果构造该类型的对象,为什么有两个默认构造函数只会出错?

问题描述 投票:0回答:1

这是一个例子:

#include <stdio.h>                                                                                             
struct C {                                                                                                     
  C() { printf("hello!\n"); }                                                                                  
  C(bool a = false) { printf("hi!\n"); }                                                                       
};                                                                                                             
                                                                                                               
int main() {                                                                                                   
  //  C c;                                                                                                     
}   

如果您取消注释

main
中的行,这是一个错误,但如果您保留注释,则不是。

我的问题是为什么这不是一个错误,除非你这样做

C c;
。例如,它应该主动并在看到类似的东西时立即说错误,因为它不可用。

换句话说:什么使重载集无效,以及为什么无参数构造函数的歧义仅在不带参数构造对象时才使其无效,而不是在编译器识别出这种可能性时才无效?

c++ oop types constructor compiler-construction
1个回答
0
投票

就像这样,它应该主动并在看到类似的东西时立即说错误,因为它不可用。

您所看到的是构造函数的特质。在这方面,构造函数被视为与其他函数相同,大概是因为更简单的语言规范(特殊情况较少的语言规范)更容易正确。

那么让我们看看使用常规函数的相同设置。这里不是两个可以不带参数调用的构造函数,而是一个名为

foo()
的函数的两个定义,每个定义都可以不带参数调用。这是相同的基本设置,其中一个定义不带参数,而另一个定义则为其单独的参数设置默认值。

int foo() { return 22; }
bool foo(bool a = false) { return a; }

int main() {                                                                                                   
    return foo(); // ERROR!
} 

使用此设置,您还会因不明确而收到错误。我希望我们能够同意这本质上是相同的情况,只是没有构造函数。

这里是有趣的部分:

foo()
can的第一个版本可以被调用。这需要一种间接的方法,但这是可以做到的。说这个设置绝对是一个错误是不公平的。 当我说“间接”时,我指的是间接。可以获取第一个
foo()
的地址(通过
static_cast
解决歧义),然后可以使用该指针来调用该函数。

int foo() { return 22; }
bool foo(bool a = false) { return a; }

int main() {                                                                                                   
    auto fptr = static_cast<int(*)()>(foo);
    return fptr(); // Programs compiles, runs, and exits with code 22.
} 

这应该表明这种情况不一定是常规函数的错误。虽然构造函数不能这样说(不能获取构造函数的地址),但构造函数是函数,并且它们具有函数的许多特征。针对这种情况进行特殊处理要么不是优先事项,要么没有带来足够的好处来证明复杂性的合理性。

(另一方面,编译器可以针对这种情况提供警告。警告通常是针对语言标准合法但可能不是程序员想要的内容发出的。编译器是否这样做取决于到特定的编译器。)

© www.soinside.com 2019 - 2024. All rights reserved.