Как вызвать перегруженный родительский класс cout friend из производного класса?


Представьте себе такую установку. Как вызвать базовый класс cout из производного класса cout? Я мог бы использовать метод getBrand(), но мне кажется, что я должен иметь прямой доступ к функции друга базового класса cout.

Я немного взломал и попробовал this.Brand, а также Просто Brand. Не повезло.

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
4 6

4 ответа:

Можно вызвать перегруженный operator << базового класса из производного класса. Поскольку вы объявили оператор другом, вы можете просто привести производный класс к базовому классу:

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

Смотрите его вживую

Бросьте его, вот так:

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

    return out;
}

Все остальные ответы правильно отвечают на ваш конкретный вопрос, но всякий раз, когда вы пытаетесь использовать полиморфизм, как это:

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

operator << соответствующий Brand будет называться вместо Cheese ' s.

Хороший способ сделать это-использовать виртуальную функцию-член 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 << для базового класса, который вызовет вашу print виртуальную функцию-член:

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

Демо

Вы, очевидно, не можете сделать ничего подобного Brand::operator<<, потому что оба operator<< определены как friend и, таким образом, они не являются функциями-членами.

Если вы хотите вызвать operator<<(std::ostream&, const Brand&), Вам просто нужно передать правильные типы, и поскольку производные классы могут быть легко приведены к базовым классам, вы можете просто сделать

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