在operator <<中动态转换为派生类型

Kev*_*aft 0 c++ dynamic-cast operator-overloading

我有一个基类Tag和一个TagSet继承自的子类Tag.

class Tag
{
  public:
    Tag(std::string);
    std::string tag;
};
std::ostream & operator <<(std::ostream &os, const Tag &t);

class TagSet : public Tag
{
public:
    TagSet();
};
std::ostream & operator <<(std::ostream &os, const TagSet &ts);
Run Code Online (Sandbox Code Playgroud)

和他们的实施

Tag::Tag(std::string t)
: tag(t)
{}

std::ostream & operator <<( std::ostream &os, const Tag &t )
{
  os << "This is a tag";
  return os;
}

TagSet::TagSet()
: Tag("SET")
{}

std::ostream & operator <<(std::ostream &os, const TagSet &ts)
{
  os << "This is a TagSet";
  return os;
}
Run Code Online (Sandbox Code Playgroud)

我想要包含一个TagList具有成员的第三个类std::vector<Tag*>,它可以包含Tag*实例或TagSet*实例.我想要定义的<<操作员TagList,它采用了这样Tag的版本,operator<<如果元素是一个TagTagSet版本operator<<如果元素是一个TagSet.这是我的尝试:

std::ostream & operator <<(std::ostream &os, const TagList &ts)
{
  for (auto t : ts.tags)
  {
    if (t->tag == "SET")
    {
      TagSet * tset = dynamic_cast<TagSet*>(t);
      os << *tset << ", ";
    }
    else os << t->tag << ", ";
  } 
}
Run Code Online (Sandbox Code Playgroud)

代码在运行时崩溃.我检查了tset指针,它不是空的.可能这是一个糟糕的演员阵容.

这样做的正确方法是什么?这个问题与operator<<函数中的consts有关吗?其他建议如何实现这一点是受欢迎的.

其余的TagList实现是为了完整性:

class TagList
{
public:
    TagList(std::vector<Tag*> taglist);
    std::vector<Tag*> tags;
    typedef std::vector<Tag*>::const_iterator const_iterator;
    const_iterator begin() const { return tags.begin(); }
    const_iterator end() const { return tags.end(); }
};
std::ostream & operator <<(std::ostream &os, const TagList &ts);
Run Code Online (Sandbox Code Playgroud)

TagList::TagList(std::vector<Tag*> tagvec)
: tags(tagvec.begin(), tagvec.end())
{}
Run Code Online (Sandbox Code Playgroud)

Som*_*ude 5

如果我可以针对输出Tag对象的问题提出不同的解决方案,那么只有一个运算符重载,Tag const&然后将该调用作为结构中的虚output函数Tag.然后在继承的类中重写该函数.

也许是这样的

struct Tag
{
    ...
    virtual std::ostream& output(std::ostream& out)
    {
        return out << "This is Tag\n";
    }

    friend std::ostream& operator<<(std::ostream& out, Tag const& tag)
    {
        return tag.output(out);
    }
};

struct TagSet : Tag
{
    ...
    std::ostream& output(std::ostream& out) override
    {
        return out << "This is TagSet\n";
    }
};
Run Code Online (Sandbox Code Playgroud)

然后输出列表

for (auto t : ts.tags)
    std::cout << *t;
Run Code Online (Sandbox Code Playgroud)