为什么当类包含虚方法时clang会创建这些隐式方法?

时间:2015-09-24 23:24:34

标签: c++ operator-overloading clang libtooling

我正在开发一个基于clang AST的工具,我很想知道为什么clang会这样工作。

这是我的意见。我有一个非常简单的类,定义如下:

class Foo {
    int foo();
};

然后在我的RecursiveASTVisitor中,我的代码如下所示:

bool MyASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl *D) {
    for (auto const & method : D->methods()) {
        llvm::outs() << method->getQualifiedNameAsString() << "(";
        for (auto const & param : method->params())
            llvm::outs() << param->getType().getAsString() << ", ";
        llvm::outs() << ")";
        if (method->isImplicit())
            llvm::outs() << " [implicit]";
        llvm::outs() << "\n";
    }
    return true;
}

所有这一切都是在所有访问过的类中定义的方法列表中吐出。这个输出正如我们所期望的那样:

Foo::foo()

现在,让我们对我们的Foo类进行一些小改动。让我们将foo()方法设为虚拟:

class Foo {
    virtual int foo();
};

现在我的输出发生了变化:

Foo::foo()
Foo::operator=(const class Foo &, ) [implicit]
Foo::~Foo() [implicit]

我的问题是,为什么在类中添加一个虚方法导致clang创建一个隐式赋值运算符和析构函数?如果我添加--std = c ++ 11,它也会创建一个隐式的移动赋值运算符。这是clang的实现细节,还是C ++标准的一部分?

1 个答案:

答案 0 :(得分:1)

原来我应该阅读clang源代码。 SemaDeclCXX.cpp有一个名为Sema::AddImplicitlyDeclaredMembersToClass的方法。有关于它为什么声明隐式副本赋值的评论:

if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
  ++ASTContext::NumImplicitCopyAssignmentOperators;

  // If we have a dynamic class, then the copy assignment operator may be
  // virtual, so we have to declare it immediately. This ensures that, e.g.,
  // it shows up in the right place in the vtable and that we diagnose
  // problems with the implicit exception specification.
  if (ClassDecl->isDynamicClass() ||
      ClassDecl->needsOverloadResolutionForCopyAssignment())
    DeclareImplicitCopyAssignment(ClassDecl);
}

所以这样做是为了确保隐含定义的方法(可能是虚拟的)最终在vtable中的正确位置。