首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Virtual operator <<和模板

Virtual operator <<和模板
EN

Stack Overflow用户
提问于 2015-11-03 17:59:53
回答 3查看 87关注 0票数 0

我正在尝试实现一种虚拟操作符<<,它允许我向cout发送一个IBase类对象,这样它就可以调用派生类的operator <<。这个是可能的吗?

代码语言:javascript
复制
class IBase
{
public:
    IBase() {};
    virtual ~IBase() {};
};

template <typename T>
class Derived
    : public IBase
{
public:
    Derived(T data);
    template <typename U>
    friend std::ostream& operator<<(std::ostream& os, const Derived<U>& dt);
private:
    T data_;
};

template <typename T>
Derived<T>::Derived(T data)
    : IBase(),
      data_(data)
{
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const Derived<T>& dt)
{
    os << dt.data_;
    return os;
}

int _tmain(int argc, _TCHAR* argv[])
{
    IBase* base = new Derived<int>(5);

    std::cout << *base;
}
EN

回答 3

Stack Overflow用户

发布于 2015-11-03 18:03:36

<<运算符是一个函数,而不是一个方法,因此它不能是虚拟的。但是,您仍然可以实现您想要的结果--还记得operator<<接受引用作为参数吗?好的,多态也适用于这些。只需添加另一个从<<操作符调用的虚拟方法。

看一下我放在一起的这个简短的例子:

代码语言:javascript
复制
#include <iostream>
#include <string>
using namespace std;

class Base {
 public:
 virtual string toString() const {
   return "base";
 }
};

class Child : public Base {
 public:
  virtual string toString()  const {
   return "child";
  }

  friend ostream& operator<<(ostream& out, const Base& b);
};

ostream& operator<<(ostream& out, const Base& b) {
    out << b.toString();
    return out;
}

int main() {
    Child c;
    cout << c;
    return 0;
}

在ideone中有一个链接:http://ideone.com/EmP1oP

票数 0
EN

Stack Overflow用户

发布于 2015-11-03 18:03:42

您的目标不能仅通过模板来实现,因为取消对模板的引用会产生一个IBase& - IBase*实例化发生在编译时,并且编译器无法访问运行时类型。

(动态分派仅在调用对象的成员函数时发生,并且二元运算符不能是其右操作数的成员。)

因此,如果您将一个取消引用的IBase*传递给operator <<,您的模板化运算符将永远不会被使用。

相反,向基础添加一个虚拟输出函数并覆盖它:

代码语言:javascript
复制
class IBase
{
public:
    IBase() {};
    virtual ~IBase() {};
    virtual std::ostream& output(std::ostream&) const = 0;
};

template <typename T>
class Derived
    : public IBase
{
public:
    Derived(T data);
    virtual std::ostream& output(std::ostream& os) const
    {
        os << data;
        return os;
    }
private:
    T data_;
};

std::ostream& operator<<(std::ostream& os, const IBase& dt)
{
    return dt.output(os);
}
票数 0
EN

Stack Overflow用户

发布于 2015-11-03 18:05:27

您可以通过简单的模板rig (此外,它不会阻止去虚拟化)的帮助,将其变为真实的虚拟。

代码语言:javascript
复制
struct X {
    virtual std::ostream& repr(std::ostream& out) const;
}

template <class X>
std::enable_if_t<
    std::is_same<
        std::void_t<
            decltype(std::declval<X>().repr(std::declval<std::ostream>()))>,
            void>::value,
    std::ostream&>
operator<<(X const& x)
{
    return x.repr(out);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33496137

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档