如何调用运算符>>在派生类?

时间:2015-04-19 15:15:32

标签: c++

如何致电运营商>>派生类的基类?在派生类中我想读A和B,但我不知道怎么做,非常感谢你!

class Base {
public:
    friend istream& operator>>(istream& input, Base &base) {
        input >> A;
    }
protected:
    int A;
};

class Derived: public Base {
public:
    friend istream& operator>>(istream& input, Derived &derived) {
        // How can I call the operator >> from base class?
        input >> B;
    }
protected:
    int B;
}

2 个答案:

答案 0 :(得分:2)

首先,由于operator>>是友元函数而不是成员函数,因此需要更改base的实现:

class Base {
public:
    friend istream& operator>>(istream& input, Base &base) {
        input >> base.A;
    }
private:
    int A;
};

对于派生:

class Derived: public Base {
public:
    friend istream& operator>>(istream& input, Derived &derived) {
        input >> static_cast<Base&>(derived);
        input >> derived.B;
    }
private:
    int B;
};

还要注意,友谊不是继承的。也就是说,你做不到

input >> static_cast<Base&>(derived).A

由于operator>>(istream& input, Derived &derived)不是Base的朋友。

另请注意,使用继承的方式存在问题且令人困惑,因为如果使用基本引用,您将获得不同的行为。即使你重写它以使用虚函数,使用base的函数也不知道会发生什么(它会吃多少流)。 有了这个,对于预期的行为是什么感到困惑:

Base b;
Derived d1;    
Base& b1 = d1;

{
  std::string_steam ss ; 
  ss << "1 2";
  ss >> b; // will set A to 1 and leave 2 in the stream
}
{
  std::string_steam ss ; 
  ss << "1 2";
  ss >> d1; // will set A to 1 and B to 2
}
{
  std::string_steam ss ; 
  ss << "1 2";
  ss >> b1; // will set A to 1 and leave 2 in stream 
}

用户(使用基本参考的功能)很难知道如何使用这样的对象。

同时阅读Liskov substitution principle

答案 1 :(得分:0)

如果你想在多态情况下使用它,你可能想要定义某种read虚函数:

class Base {
public:
    virtual istream& read(istream& in) {
        return in >> A;
    }
// private: // for demo
    int A = 0;
};

class Derived: public Base {
public:
    virtual istream& read(istream& in) {
        Base::read(in);
        return in >> B;
    }
//private: // for demo
    int B = 0;
};

istream& operator>>(istream& input, Base &base) {
    return base.read(input);
}

请注意,在这段代码中,运算符>>不是任何人的朋友。

Live demo

使用输入1 2,以下程序按预期工作。

int main() {
    Derived d;
    Base& b = d;

    cout << d.B << " - " << d.A << endl; // 0 - 0

    cin >> b; 

    cout << d.B << " - " << d.A << endl; // 1 - 2

    return 0;
}