typedef别名的析构函数

时间:2018-09-10 11:27:39

标签: c++ language-lawyer destructor typedef

#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是类型的别名。在这种情况下,ABA的别名。

为什么这也适用于析构函数的名称?非常感谢您参考语言规范。

编辑:它是使用macOS High Sierra版本10.13.3上的Apple LLVM版本9.1.0(clang-902.0.39.1)编译的。

2 个答案:

答案 0 :(得分:21)

  

为什么这也适用于析构函数的名称?

因为标准说:

  

[class.dtor]

     

在显式析构函数调用中,析构函数由〜指定,后跟类型名称或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])包含一个   在嵌套名称说明符中,类型名称会在   嵌套名称说明符指定的范围。同样,在   格式的合格ID:

     

嵌套名称说明符选择类名称::〜类名称

     

在与第一个类名相同的范围内查找第二个类名。   [示例:

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
}
     

-示例example]

答案 1 :(得分:6)

因为当您写~AB()时,您不是在命名或调用析构函数。您正在编写~,后跟 the 类的名称,由于指定的语义将这些标记彼此相邻地写入,因此将自动设置析构函数调用。

通常这是学术性的,但是在这里您知道为什么它很重要。

类似地,通过编写AB(),您并不是在“调用构造函数”,即使这看起来像是一个函数调用,并且许多新手都以这种方式解释代码。 (这会在尝试调用不带参数推导的模板构造函数时带来乐趣和游戏性:如果无法命名该构造函数,则无法提供这些参数!)

实际上,构造器和析构器在技术上甚至都没有名称。

这些细微差别使C ++很有趣,对吧?