[英]Destructor of typedef alias
#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)编译的。
为什么这也适用于析构函数的名称?
因为标准说:
[class.dtor]
在显式的析构函数调用中,析构函数由〜后跟一个type-name或decltype-specifier来指定,该类型名称或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])包含嵌套名称说明符,则类型名称将在nested-name-specifier指定的作用域中作为类型查找。 同样,在表单的qualified-id中:
nested-name-specifieropt class-name :: ~class-name
第二个类名在与第一个类相同的范围内查找。 [例如:
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 }
- 结束例子]
因为当您编写~AB()
您没有命名或调用析构函数。 你写~
后跟类
的
名称,析构函数调用自动配置为写彼此相邻的令牌的指定语义的结果。
通常这是学术性的,但在这里你明白为什么它很重要。
类似地,通过编写AB()
您不是“调用构造函数”,即使这看起来像函数调用,并且许多语言新手以这种方式解释代码。 (当试图在没有参数推断的情况下调用模板构造函数时,这可以带来乐趣和游戏:如果不能命名构造函数,则无法提供这些参数!)
实际上,构造函数和析构函数在技术上都没有名称!
这些细微差别让C ++变得有趣,对吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.