类类型的直接析构函数调用

Directly destructor call of class type

本文关键字:析构 函数调用 类型      更新时间:2023-10-16

代码:

#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,由于命名析构函数的特殊规则,它仍然是病态的,其中类型必须完全匹配;不能使用嵌套名称说明符表示派生类来命名基类析构函数。