C ++中奇怪的解析:int f(int(arg))等效于int f(int arg) - 任何人都能解释一下吗?

时间:2015-07-29 16:51:12

标签: c++

当我试图用这样的单个参数构造一个对象时,我的一个同事发现了这个:

char testString[] = "test string";
...
MyClass instance(QString(testString));

他们意识到如果你用一个参数构造函数式习语,它将被解析为一个前向声明的函数,例如

char test[] = "hello";

MyClass instance1(0, test) //constructs an object
MyClass instance2(test) //invalidly forward-declares a function

但他们被他们认为应该工作的东西困扰,因为它在括号内包含函数式转换或单参数构造函数调用。

我已经发现他们的构造函数调用被解析为:

MyClass instance(QString testString);

它不是将变量testString传递给强制转换运算符,而是声明一个具有相同名称参数的函数。我的问题是,它为什么这样做?它似乎允许参数的名称用括号括起来。

2 个答案:

答案 0 :(得分:8)

  

这是我的一位同事发现的

不,它几十年前被“发现”,是一种非常着名的语言怪癖。

  

我的问题是,为什么会那样做?它似乎允许参数的名称用括号括起来。

是的。 C声明语法不是那么规定,不允许这种特定情况。在一般情况下,它对于更复杂的结构非常有用:

void foo(int (*func)(char));
// (takes a pointer to a function returning int and taking char, bool)

// as opposed to:
void foo(int *func(char));
// (takes a function returning int* and taking char)

// as this is literally equivalent to the clearer:
void foo(int* func(char));

,在C ++中:

void foo(int (&array)[5]) {}
// (takes a reference to an array of five integers)

// as opposed to:
void foo(int &array[5]) {}
// (takes an array of five `int&`s ... and fails to compile accordingly)

对于您的具体案例,这是一个公认的笨拙的解决方案:

MyClass instance((QString(testString)));
//               ^                   ^

或者,自C ++ 11以来更有帮助:

MyClass instance(QString{testString});
//                      ^          ^

这实际上是引入统一初始化语法的驱动因素之一。

附录

  

如果你用一个参数构造函数式习语,它将被解析为一个前向声明的函数,例如

MyClass instance2("hello") //invalidly forward-declares a function

这种说法完全是不真实的。

此外,char *testString = "test string";已被弃用17年,非法为4。

答案 1 :(得分:2)

在C ++和C语言中,声明符可能被任意数量的括号包围:

int a;
int (b);
int ((c));
int f(int (x));

这主要用于区分函数指针声明符和返回指针类型的函数的声明符。例如,此处f是一个指向函数的指针,该函数接受int并返回int

int (*f)(int x);

换句话说,如果(*f)(x)int,则xint。在这里,f是一个函数,它接受int并返回指向int的指针:

int *f(int x);

换句话说,如果*f(x)int,则xint