为什么在 C++ 中调用此虚函数会导致基类出现'missing symbol'错误?

Why does calling this virtual function in C++ result in a 'missing symbol' error from the base class?

本文关键字:missing 错误 symbol 基类 调用 C++ 函数 为什么      更新时间:2023-10-16

>我有一个虚拟类,定义如下:

  template<typename TId, typename TValue>
  class Resource {
    private:
      /// Next item in the chain
      unique_ptr<Resource<TId, TValue>> data;
    protected:
      /// The id this value
      TId id;
      /// The value on this value
      TValue value;
    public:
      /// Create a new instance and assign the values to it
      Resource(TId id, TValue value) {
        this->id = id;
        this->value = value;
      }
      /// Destructor
      virtual ~Resource() {
      }
      /// Safely clone a new instance of this
      virtual Resource<TId, TValue> *Clone();
      ... other stuff removed for brevity ...
      /// Create a new resource chain with a custom filter
      Option<Resource<TId, TValue>*> Filter(std::function< bool(Resource<TId, TValue>*) > filter) {
        auto iter = this->Iter<Resource<TId, TValue>>(filter);
        if (iter.Any()) {
          auto index = 0;
          auto root = (*iter.First())->Clone();
          iter.Each([&] (Resource<TId, TValue>* r) {
            if (index != 0) {
              root->Push(r->Clone());
            }
            ++index;
          });
          return Some<Resource<TId, TValue>*>(root);
        }
        return None<Resource<TId, TValue>*>();
      }
  };

我已经在测试中轻松实现了这一点,例如:

enum RType {
  ThingOne = 1,
  ThingTwo = 2
};
class RValue : public Resource<RType, i32> {
  public:
    RValue(int value) : Resource(ThingOne, value) {
    }
    ~RValue() {
    }
    Resource<RType, i32>* Clone() {
      return new RValue(this->value);
    }
};

铌。注意克隆的用法:

root->Push(r->Clone());

但是,在编译时,我得到:

[ 88%] Building CXX object CMakeFiles/test-resource.dir/tests/test-resource.cpp.o
Linking CXX executable tests/test-resource
Undefined symbols for architecture x86_64:
  "npp::Resource<RType, int>::Clone()", referenced from:
      vtable for npp::Resource<RType, int> in test-resource.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [tests/test-resource] Error 1
make[1]: *** [CMakeFiles/test-resource.dir/all] Error 2

编译器是 clang,平台是 OSX。

这是怎么回事?

为什么在调用函数时,派生类中的实现不会自动解析?

是因为这是一个模板化的方法吗?

完整的代码可以在此要点中找到,以供参考:https://gist.github.com/shadowmint/d49650668e9a74c324a1

如果不想实现基类的虚拟成员函数,则必须将其声明为纯虚拟:

  //                                     vvv-- here
  virtual Resource<TId, TValue> *Clone() = 0;

否则,链接器将搜索你在为基类生成虚拟函数表时声明但未实现的函数(可以在收到的错误消息中看到这一点)。

请注意,在其中声明纯虚拟成员函数将使类抽象。