【问题标题】:How to invoke an overloaded parent cout friend class from a derived class?如何从派生类调用重载的父 cout 朋友类?
【发布时间】:2017-11-22 06:28:00
【问题描述】:

设想如下设置。如何从派生类cout 中调用基类cout?我可以使用getBrand()方法,但我觉得我应该可以直接访问基类的cout友元函数。

我尝试了一下,尝试了this.BrandBrand。没有运气。

class Brand {
public:
    Brand(std::string brand):brand_(brand) {};
    friend std::ostream & operator << (std::ostream & out, const Brand & b) {
        out << b.brand_ << ' ';
        return out;
    }   
    std::string getBrand()const { return brand_; }     
private:
    std::string brand_;
}

class Cheese : public Brand {
public:
    Cheese(std::string brand, std::string type):Brand(brand), type_(type) {};
    friend std::ostream & operator << (std::ostream & out, const Cheese & c) {
        out << /* THIS.BRAND?! BRAND?! getBrand() meh.. */ << ' ' << c.type_ << std::endl; // <-- HERE
        return out;
    }
private:
    std::string type_;
}

int main() {
    Cheese c("Cabot Clothbound", "Cheddar");
    std::cout << c << std::endl;
} 

期望的输出

Cabot Clothbound Cheddar

【问题讨论】:

  • Brandoperator&lt;&lt; 将尾随换行符放入流中时,输出应该如何Cabot Clothbound Cheddar
  • 好点,但题外话。已编辑和删除。

标签: c++ class oop c++11 inheritance


【解决方案1】:

所有其他答案都正确回答了您的具体问题,但每当您尝试使用这样的多态性时:

Brand const &c = Cheese("Cabot Clothbound", "Cheddar");
std::cout << c << std::endl;

将调用对应于Brandoperator &lt;&lt;而不是Cheese的。

最好的方法是使用一个虚拟的print成员函数:

class Brand {
public:
    Brand(std::string const & brand):brand_(brand) {}
    virtual ~Brand() {}
    virtual void print(std::ostream & out) const {
        out << brand_;   
    }
    std::string const & getBrand()const { return brand_; }     
private:
    std::string brand_;
};
class Cheese : public Brand {
public:
    Cheese(std::string const & brand, std::string const & type):Brand(brand), type_(type) {}
    void print(std::ostream & out) const override {
        Brand::print(out); // calling base print()
        out << ' ' << type_ << std::endl;
    }
private:
    std::string type_;
};

然后,您只需要一个 operator &lt;&lt; 用于基类,它将调用您的 print 虚拟成员函数:

std::ostream & operator << (std::ostream & out, const Brand & b) {
    b.print(out);
    return out;
}

DEMO

【讨论】:

  • 反应很好;这次真是万分感谢。尽管它没有像上面那样直接回答这个问题,但我还是很想接受这个作为答案。无论如何,谢谢你花时间教我这个,我很感激。 :^)
【解决方案2】:

你显然不能像Brand::operator&lt;&lt; 那样做任何事情,因为operator&lt;&lt; 都被定义为friend,因此它们不是成员函数。

如果你想调用operator&lt;&lt;(std::ostream&amp;, const Brand&amp;),你只需要传递正确的类型,因为派生类可以很容易地转换为基类,你可以这样做

friend std::ostream & operator << (std::ostream & out, const Cheese & c) {
    out << static_cast<const Brand&>(c) << ' ' << c.type_ << std::endl;
    return out;
}

【讨论】:

    【解决方案3】:

    您可以从派生类调用基类的重载operator &lt;&lt;。由于您将运算符声明为友元,您可以简单地将派生类转换为基类:

    class Cheese : public Brand {
    public:
        Cheese(std::string brand, std::string type):Brand(brand), type_(type) {};
        friend std::ostream & operator << (std::ostream & out, const Cheese & c) {
    
            //ADDED
            out << static_cast<const Brand&>(c) << c.type_ << std::endl;
            return out;
        }
    private:
        std::string type_;
    };
    

    输出:

    Cabot Clothbound Cheddar
    

    See it Live

    【讨论】:

    • 比你快 1 分钟,但你有一个现场演示,而我没有,所以请接受我的投票。 =)
    【解决方案4】:

    像这样投射它:

    friend std::ostream& operator<<(std::ostream& out, const Cheese& c)
    {
        out << static_cast<const Brand &>(c);
        out << c.type_ << std::endl;
    
        return out;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-04
      • 1970-01-01
      • 2018-01-05
      • 2020-08-10
      • 2011-05-04
      • 1970-01-01
      • 1970-01-01
      • 2015-12-30
      • 2020-02-25
      相关资源
      最近更新 更多