About clang’s -Wweak-vtables warning

The full warning message looks like this:

warning: ‘XXX’ has no out-of-line virtual method definitions; its vtable
will be emitted in every translation unit [-Wweak-vtables]

This warning usually comes from code like:

// XXX.h中
class BaseData
{
public:
    virtual ~BaseData() = default;
    int _base_data = 0;
};

class DerivedDataA final : public BaseData
{
public:
    int _derived_data_a = 0;
};

class DerivedDataB final : public BaseData
{
public:
    int _derived_data_b = 0;
};

In this header, a base class BaseData and two derived classes DerivedDataA and DerivedDataB are declared. The idea was to describe two kinds of data classes A and B with some commonality. If that was all, polymorphism would not be needed, and the base destructor could be non‑virtual. But since the use case required storing both derived types in a common container like std::vector<BaseData*>, the base destructor had to be virtual. With RTTI or dynamic_cast, type distinction is possible. At this point, including the header in multiple cpp files triggers the warning:

warning: ‘BaseData’ has no out-of-line virtual method definitions; its vtable
will be emitted in every translation unit [-Wweak-vtables]

In fact, all three classes receive the same warning. The warning does not affect runtime behavior, but it means each translation unit generates a copy of the vtable, later deduplicated at link time. This slows linking. To avoid it, provide an out‑of‑line definition for at least one virtual function. For example, defining a destructor body works, but that makes the class non‑trivial. If cleanup is needed, that is fine, but in this example no special cleanup was required. So instead a harmless virtual function was added:

// XXX.h
class BaseData
{
public:
    virtual ~BaseData() = default;
    virtual std::string getType();
    int _base_data = 0;
};

class DerivedDataA final : public BaseData
{
public:
    std::string getType() override;
    int _derived_data_a = 0;
};

class DerivedDataB final : public BaseData
{
public:
    std::string getType() override;
    int _derived_data_b = 0;
};

// XXX.cpp
#include "XXX.h"

std::string BaseData::getType()
{
    return "base";
}

std::string DerivedDataA::getType()
{
    return "derived_a";
}

std::string DerivedDataB::getType()
{
    return "derived_b";
}

This removes the warning and reduces link overhead.

博主友情提示:

如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。