类类型的直接析构函数调用
Directly destructor call of class type
代码:
#include <iostream>
namespace A
{
class D{ };
class C
{
public:
static const int a=7;
~C(){ std::cout << "Destroyed"; }
C() { std::cout << "Created"; }
};
}
int main()
{
typedef A::C zlp;
zlp *z= new zlp();
z->A::D::~zlp();//error: ‘A::D’ is not a base of ‘zlp {aka A::C}’
}
我读了3.4.3/1 N3797。这里写着
如果pseudo-destructor-name(5.2.4)包含嵌套名称说明符,类指定的作用域中查找类型名nested-name-specifier。类似地,在形式为:
的限定id中nested-name-specifier_opt class-name :: ~ class-name
第二个类名在与第一个类名相同的作用域中查找。
这个引语并没有说nested-name-specifier_opt class-name
一定是zlp
的基型。你能解释这种行为吗?我想找一份相应的参考标准
编译器可以尝试解析构造
z->A::D::~zlp
as " prefix -expression ->
template
optid-expression"(普通成员访问表达式)或作为"postfix-expression ->
pseudo-destructor-name"(参见语法中的[expr]。
[expr。/1,在Pseudo析构函数调用中,只允许左操作数为标量类型。显然,z->A::D::~zlp()
不是一个有效的伪析构函数调用。
该标准的目的是,当左操作数为类类型时,第一种语法结果适用(因为要求标量类型的第二种语法结果显然是错误的)。在c++ 20中删除了语法歧义。这与这个问题没有直接关系,所以我就不再深入讨论了。
回到N3797,问题是我们是否可以将z->A::D::~zlp
解释为形式为&;postfix-expression ->
template
optid-expression&;的有效成员访问表达式。它实际上归结为A::D::~zlp
是否是一个有效的id表达式。[expr.prim。通用]规范id-表达式,第9段特别关注限定id,其中嵌套名称说明符命名一个类:
一个嵌套名称说明符,表示一个类,可选地后跟关键字
template
(14.2),然后后跟该类(9.2)或它的一个基类(第10条)的成员名,就是限定标识;3.4.3.1描述了出现在qualified-ids中的类成员的名称查找。结果是成员。结果的类型就是成员的类型。如果成员是静态成员,则结果为左值成员函数或数据成员和右值,否则。(注意:…使用class-name::
~
class-name时,两个类名指同一类;这个符号命名析构函数(12.4)。[…]
因为~zlp
既不是A::D
的成员,也不是A::D
基类的成员(事实上,A::D
没有基类),所以A::D::~zlp
甚至不是一个有效的限定id。即使它是限定id,由于命名析构函数的特殊规则,它仍然是病态的,其中类型必须完全匹配;不能使用嵌套名称说明符表示派生类来命名基类析构函数。
- 析构函数调用
- 在具有向量的类构造函数中进行析构函数调用
- 从 c++ 中派生类的析构函数调用虚函数
- C++析构函数调用两次,堆栈分配的复合对象
- C++ 在析构函数调用之前删除的动态成员数组
- 析构函数调用c++中的一个向量
- Singleton模式中的手动析构函数调用:调用多次
- 从内部类的析构函数调用虚拟函数
- 与 boost odeint 集成期间的析构函数调用
- 堆栈展开如何与析构函数调用有关?
- C++:优化析构函数调用
- 以逗号分隔的表达式中的析构函数调用
- GCC 9.1 返回 void& 作为显式析构函数调用的结果类型。这是一个错误吗?
- 从C++中的虚拟析构函数调用虚拟方法
- 从指针返回对象时出现意外的析构函数调用
- 使用 decltype 显式析构函数调用
- C++析构函数调用了错误的对象
- 了解虚拟函数和析构函数调用
- 多重继承析构函数调用他自己和父析构函数?c++
- 析构函数调用表单不适当的库