【问题标题】:passing abstract class to i/o macro将抽象类传递给 i/o 宏
【发布时间】:2012-10-22 12:39:08
【问题描述】:

我通过确保继承层次结构中的类实现虚拟读写功能来实现序列化:

class base
{
     ...

     virtual void read(std::istream&)=0;
     virtual void write(std::ostream&) const=0;
     virtual std::string is_a() const;
};

BEGIN_NAMESPACE_1(io)
    SERIALISE(base)
END_NAMESPACE_1

宏“SERIALISE”实现了“serialise”和“deserialise”函数的重载,以允许通过基类指针轻松输入/输出:

#define SERIALISE(TYPE)\
void deserialise( boost::shared_ptr<TYPE>& dat, std::istream& ifs )\
{\
    std::string type;\
    read(type, ifs);\
\
    dat = TYPE::make_##TYPE(type);\
    dat->read(ifs);\
}\
\
void serialise( const boost::shared_ptr<TYPE>& dat, std::ofstream& ofs )\
{\
    write(dat->is_a(), ofs);\
    dat->write(ofs);\
}

但是,如果基类包含纯虚函数,我会收到编译器错误“无法分配抽象类型“base”的对象,因为以下函数在“base”中是纯的......”,大概是因为编译器试图当类名传递给宏调用时实例化抽象基类。有没有办法挽救这种 i/o 设计?

【问题讨论】:

  • 如果您不向我们展示宏包含的内容或编译器错误是什么,我们将无法回答...
  • 好的,抱歉,我已经更新了问题,希望它现在包含足够的细节。我以为我在处理标准问题时犯了一个简单的错误......
  • 为原型化的纯虚函数提供函数定义。尽管成员函数可能是纯虚函数,但可以提供函数定义,而不仅仅是基类中的原型。这个定义可以从派生类中调用。
  • 您可以将宏调用替换为您的抽象类之一的实际扩展并检查编译器错误。这样追踪起来会容易得多。
  • 回复 damienh:这似乎并不能解决问题,尽管如果我将方法设为虚拟,它当然可以工作。不过,我真的不希望实例化基础。

标签: c++


【解决方案1】:

您不能实例化抽象基类或将其用作函数的值参数。

模板显式 shared_ptr(Y * p);要求:p 必须是 可转换为 T *。 Y 必须是完整类型。 表达式 delete p 必须格式正确,不得调用未定义的行为,也不得 抛出异常。

效果:构造一个拥有指针 p 的 shared_ptr。

后置条件:use_count() == 1 && get() == p。

抛出:std::bad_alloc,或当 a 无法获取内存以外的资源。

异常安全:如果抛出异常,则调用 delete p。

注意:p 必须是指向通过 C++ 分配的对象的指针 new 表达式 or 为 0。使用 count 为 1 的后置条件成立 即使 p 为 0;对值为 0 的指针调用 delete 是 无害。

在这种情况下,编译器不必将模板 shared_ptr 解析为内部具有 TYPE 类型的值,因为这些值永远无法实例化。

【讨论】:

  • 我的问题是序列化/反序列化函数应该根据 shared_ptr 来表示。您是否建议 shared_ptrs 应该保存指针类型?
  • afaik shared_ptr 中的模板参数指的是指针的类型,在任何时候都不会将该类型实例化为值,将指针存储在 shared_ptr 中似乎没有意义...
  • @user588241 对不起,我错了,你不能那样做。我已经从文档中留下了一个报价。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多