从继承的模板类正确实现虚函数

时间:2019-04-15 11:26:35

标签: c++

我对这里有些困惑!假设我有一个界面

template <typename T>
class JsonSerializable {

public:

    virtual json AsJson() const;

    virtual T FromJson(json in) const;

};

如何在类或结构中正确使用此接口:

struct X : public JsonSerializable<X>
{
    float a;
    float b;

    virtual json AsJson() const override
    {
      return json();
    }

    RankingInfoTerm FromJson(json in)
    {
        RankingInfoTerm out;
        return out;
    }

};

现在,无论我尝试哪种操作,我都只会收到一堆链接器错误。我怀疑我缺少了非常明显的东西。感谢您的帮助和解释!

2 个答案:

答案 0 :(得分:3)

您没有提供我们可以尝试使用的任何正确代码,也没有显示出什么类型的错误消息特别困扰您,但是这里是有关如何从模板接口覆盖方法的示例:

template <class T>
class JsonSerializable {
public:
    virtual ~JsonSerializable() = default;
    virtual T fromJson(/* inpur args here */) = 0;
};

template <class T>
class X: public JsonSerializable<T> {
public:
    ~X() override = default;
    T fromJson(/* inpur args here */) override {
        // put here some real impl
        return T();
    }
};

int main() {
    std::shared_ptr<JsonSerializable<float> > ptr2Base;
    ptr2Base.reset(new X<float>);  // template arguments of X and SerializableJson must be the same
    std::cout << ptr2Base->fromJson() << std::endl;
    return 0;
}

fromJson签名中,我没有使用任何输入参数只是为了编译示例。当然,稍后您可能需要编写实际的实现:

T fromJson(const SomeKindOfJson& json) {
    // convert json to type T and return it
}

答案 1 :(得分:2)

现在让我们假设您想从json创建一个全新的对象。提供签名后,其外观必然类似于以下内容:

X instance;
X instance = tmp.fromJson(data);

因此,您需要先创建一个对象,然后在其上可以调用fromJson,只是用在fromJson中创建的对象覆盖它–或者您也可以创建临时的,然后再次丢弃。

好的,如果您已经有另一个对象,则可以滥用以构造一个完全不相关的对象。并不是一个很好的设计...

您想要的代码是:

X instance;
instance.fromJson(data);

您不会以这种方式创建不必要的临时对象,但需要适当地调整功能:

virtual void fromJson(JSON const& json);
//       ^                             ^ non-const!

您可能正在寻找写的可能性:

X instance = X::fromJson(data);

问题:您需要一个静态函数,但是这样的不能是虚拟的。但是,一个解决方案可能看起来像这样:

template <typename T>
class JsonSerializable
{
public:
    virtual json asJson() const;

    static T fromJson(json in)
    {
        T t;
        t.readJson(in);
        return t;
    }

private:
    virtual void readJson(json in) = 0;
};

当时的静态和非虚拟函数将调用另一个私有的 but 虚拟函数。