【问题标题】:Virtual operator << and templates [duplicate]虚拟运算符 << 和模板 [重复]
【发布时间】:2015-11-03 09:59:53
【问题描述】:

我正在尝试实现一种虚拟运算符

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;
}

【问题讨论】:

    标签: c++


    【解决方案1】:

    operator<< 将引用作为参数?好吧,多态性也适用于那些。只需添加另一个您从

    看看我整理的这个简短的例子:

    #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

    【讨论】:

      【解决方案2】:

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

      (只有在调用对象的成员函数时才会发生动态调度,并且二元运算符不能是其右手操作数的成员。)

      因此,如果您将取消引用的IBase* 传递给operator &lt;&lt;,则永远不会使用您的模板化运算符。

      相反,将虚拟输出函数添加到基础并覆盖它:

      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);
      }
      

      【讨论】:

        【解决方案3】:

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

        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);
        }
        

        【讨论】:

          猜你喜欢
          • 2020-09-20
          • 2016-02-03
          • 2011-09-08
          • 2021-11-12
          • 2019-10-21
          • 1970-01-01
          • 2021-09-19
          • 1970-01-01
          相关资源
          最近更新 更多