我对这里有些困惑!假设我有一个界面
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;
}
};
现在,无论我尝试哪种操作,我都只会收到一堆链接器错误。我怀疑我缺少了非常明显的东西。感谢您的帮助和解释!
答案 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 虚拟函数。