5.2.4 伪析构函数调用

来源:互联网 发布:如何网络兼职赚钱 编辑:程序博客网 时间:2024/05/22 06:35

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();

这段代码是在vc6中通过编译的。可以看到,对象类型为const int,而伪析构函数名所指定的类型则为doublevc6intdouble的差异都没有检测出来,更不会检测cv限定符的不同了。不过vc6还是会对伪析构函数名中(可能)的两个type-name进行类型一致性检测。