尝试理解C++标准中[class.qual]/2的含义

5

根据我在这里得到的答案,下面的代码虽然被clangvs2015接受,但是其实是格式不正确的。

#include <iostream>
class A {
public:
    A() { std::cout << "A()" << '\n'; }
};

int main()
{
  A::A();
}

尽管下面的代码在三个编译器中似乎都可以工作(参见实时示例),但根据[class.qual/2]所述,该代码无法正确编译。我是否遗漏了什么?

#include <iostream>
struct B { B() { std::cout << "B()" << '\n'; } };
struct A : public B { };
int main()
{
    A::B();
}

此外,根据[class.qual]/2,下面的代码是良好的形式,在这种情况下,所有3个编译器都会产生预期的输出(请参见此示例)。
include <iostream>
struct B { B() { std::cout << "B()" << '\n'; } };
struct A : public B { using B::B; A() { std::cout << "A()" << '\n'; }  void f() { B(); } };
int main()
{
    A a;
    a.f();
}

输出:

B()
A()
B()

但我想知道使用声明命名构造函数的作用是什么,就像上面类A中的using B::B;。请注意,无论B是否为A的基类,在这种情况下using-declaration都是完全无关紧要的。

1个回答

3

我认为你的第二个示例是格式正确的。在[class.qual]/2规则中指出,如果在C++中查找嵌套名字限定符后指定的名称时,该名称指向了C类的注入类名,则该名称引用构造函数。对于A::B这种情况,嵌套名字限定符后指定的名称是B的注入类名(由于继承关系可见),而不是A的注入类名。因此,A::B无歧义地命名一个类型,A::B()创建一个临时的B实例。

使用声明来命名构造函数可以很有用,以提升基类构造函数带参数的功能:

struct B { B(int a) { std::cout << "B " << a << '\n'; } };
struct A : public B { using B::B; };
int main()
{
    A a{1}; //would not be valid without the using-declaration
}

标准文有点长,不适合贴在我的问题中,但你可能想看一下[class.inhctor] - TartanLlama
在快速查看了[class.inhctor]之后,我必须同意你的观点。它似乎回答了我的第二个问题(+1)。但是我仍然不确定我的第一个问题。 - Belloc
@Belloc 它和什么相矛盾了呢?B::A() 声明了一个函数,B::A ba; 创建了一个类型为 A 的自动变量 ba - TartanLlama
这属于[class.qual]/2:这样的构造函数名称只能在命名构造函数的声明符或using-declaration中使用。 - Belloc
@Belloc 那个讨论是关于 A::A() 的,它与 B::A() 完全不同。前者可以在 [class.qual]/2 下命名构造函数,但只能在声明符号等中使用,而后者不命名构造函数,因此该规则不适用。 - TartanLlama
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接