#include <iostream>
struct A { ~A(); };
A::~A() {
std::cout << "Destructor was called!" << std::endl;
}
typedef A AB;
int main() {
AB x;
x.AB::~AB(); // Why does this work?
x.AB::~A();
}
以上程序的输出为:
Destructor was called!
Destructor was called!
Destructor was called!
我假设前两行属于用户析构函数调用,而第三行是由于退出main
函数的作用域时调用了析构函数。
据我了解,typedef是类型的别名。在这种情况下,AB
是A
的别名。
为什么这也适用于析构函数的名称?非常感谢您参考语言规范。
编辑:它是使用macOS High Sierra版本10.13.3上的Apple LLVM版本9.1.0(clang-902.0.39.1)编译的。
答案 0 :(得分:21)
为什么这也适用于析构函数的名称?
因为标准说:
[class.dtor]
在显式析构函数调用中,析构函数由〜指定,后跟类型名称或decltype-specifier 表示析构函数的类类型。 ...
typedef别名是一个类型名称,它表示与该类本身的类型名称相同的类。
规则甚至有一个澄清的例子:
struct B { virtual ~B() { } }; struct D : B { ~D() { } }; D D_object; typedef B B_alias; B* B_ptr = &D_object; void f() { D_object.B::~B(); // calls B's destructor B_ptr->~B(); // calls D's destructor B_ptr->~B_alias(); // calls D's destructor B_ptr->B_alias::~B(); // calls B's destructor B_ptr->B_alias::~B_alias(); // calls B's destructor }
有关名称查找的其他说明,还提供适用于该问题的示例:
[basic.lookup.qual]
如果伪析构函数名称([expr.pseudo])包含一个 在嵌套名称说明符中,类型名称会在 嵌套名称说明符指定的范围。同样,在 格式的合格ID:
嵌套名称说明符选择类名称::〜类名称
在与第一个类名相同的范围内查找第二个类名。 [示例:
struct C { typedef int I; }; typedef int I1, I2; extern int* p; extern int* q; p->C::I::~I(); // I is looked up in the scope of C q->I1::~I2(); // I2 is looked up in the scope of the postfix-expression struct A { ~A(); }; typedef A AB; int main() { AB* p; p->AB::~AB(); // explicitly calls the destructor for A }
-示例example]
答案 1 :(得分:6)
因为当您写~AB()
时,您不是在命名或调用析构函数。您正在编写~
,后跟 the 类的名称,由于指定的语义将这些标记彼此相邻地写入,因此将自动设置析构函数调用。
通常这是学术性的,但是在这里您知道为什么它很重要。
类似地,通过编写AB()
,您并不是在“调用构造函数”,即使这看起来像是一个函数调用,并且许多新手都以这种方式解释代码。 (这会在尝试调用不带参数推导的模板构造函数时带来乐趣和游戏性:如果无法命名该构造函数,则无法提供这些参数!)
实际上,构造器和析构器在技术上甚至都没有名称。
这些细微差别使C ++很有趣,对吧?