5.2.4 伪析构函数调用
5.2.4 伪析构函数调用
1、在点号.或箭头->之后的pseudo-destructor-name代表了由type-name命名的非类类型的析构函数。pseudo-destructor-name只能用作函数调用操作符()的操作数,此类调用的结果为空类型,它的唯一作用在于计算点号或箭头前面的后缀表达式。例如:
typedef int I;
I x = 10;
x.I::~I(); // or x.~I();
x = 20;
上面的x.I::~I();语句其实是调用了int类型的析构函数,但这并不会销毁x对象,x对象还能正常使用,x.I::~I();在此处并无实质作用。另外,如果将x.I::~I();改为(++x) .I::~I();,按照标准的要求,虽然I::~I()的调用不起作用,但(++x)的执行还是应该进行的。可是在vc6.0的环境中进行编译,却并没有执行增1操作,vc6.0完全忽略伪析构函数调用代码,连debug都无法跟踪到。另外还有几点需要强调,由于伪析构函数的调用要求通过type-name进行,所以将x.I::~I();改为x.int::~int();是不正确的,因为int并不是type-name,所以需要使用一个间接的类型定义名I。按照标准,type-name包括3部分:
type-name:
class_name |
enum_name |
typedef_name;
由于伪析构函数要求是非类类型,所以上述的class_name可以去除(但并不代表不能这样使用,只不过如此一来就不是伪析构函数调用,而是真实的调用了类的析构函数),剩下来还包括两类:枚举名和类型定义名。上面的代码演示了typedef_name,对于enum_name,其合适的代码应该如下:
enum TOKEN
{
CHAR
} token;
token.TOKEN::~TOKEN();
但vc6.0并不接受上述代码,出错信息为:error C2039: '__dtor' : is not a member of 'TOKEN'。要正确调用枚举的析构函数,还是需要借助类型定义名,以下代码在vc6中能编译通过:
typedef enum TOKEN
{
CHAR
} Token;
Token token;
token.Token::~Token();
2、点号操作符的左边必须为标量类型。箭头操作符的左边必须为指向标量类型的指针。这个标量类型便是对象类型。通过伪析构函数名指定的类型应该同对象类型一致。更进一步,在如下形式的伪析构函数名中
::opt nested-name-specifieropt type-name :: ˜ type-name
其两个type-name必须指向相同的标量类型。另外,对象类型的cv限定也应该同伪析构函数名所指定类型的cv限定一致。在vc6中并不对对象类型和伪析构函数名指定的类型进行一致性检查,看如下的代码:
typedef int I;
typedef double D1;
typedef double D2;
const I x = 10;
double d;
x.D1::~D2();