2011-12-31 14 views
2

私は次のような問題があります:クラスItemが製品のシリアル番号を保持しているとします。 クラスBookItemのシリアル番号を継承するItemです。すべてのクラスにoperator>>を作成して使用する必要があります。私はoperator>>からItemまでを作成してから、その本のistreamの実装でそれを呼び出すことを考えましたが、どのようにすればよいかわかりません。演算子>>を継承できますか?

コードは次のようになります:

class Item 
{ 
protected: 
    int _sn; 
public: 
    Item(); 
    ~Item(); 
    ... 
    const istream& operator>>(const istream& in,const Item& x) 
     { 
     int temp; 
     in>>temp; 
     x._sn=temp; 
     return in; 
     } 
}; 

class Book 
{ 
private: 
    char _book_name[20]; 
public: 
    Book(); 
    ~Book(); 
    ... 
    const istream& operator>>(const istream& in,const Book& x) 
     { 
     char temp[20]; 
     ////**here i want to use the operator>> of Item**//// 
     in>>temp; 
     strcpy(x._book_name,temp); 
     return in; 
     } 
}; 

int main() 
{ 
Book book; 
in>>book; //here i want to get both _sn and _book_name 
} 

これはさえ可能ですか?

答えて

10

まず、operator>>は、無料の関数またはfriendでなければなりません。左側がクラスタイプではないからです。第2に、lhsは非const参照(ストリームが抽出時に状態を変更するため)でなければならず、同じことが2番目のパラメータ(状態を変更する場合は非constにする必要があります)になります。このことを念頭に置いて、ここでは、オペレータがどのように見えるべきかです:私はあなたがC++で何をやるべきれるstd::stringに(char name[20] + strncpy)の取り扱いお使いのCスタイルの文字列を変更し

class Item 
{ 
protected: 
    int _sn; 
public: 
    Item(); 
    ~Item(); 
    // ... 
    friend std::istream& operator>>(std::istream& in, Item& item){ 
     return in >> item._sn; 
    } 
}; 

class Book 
    : public Item 
{ 
private: 
    std::string name; 
public: 
    Book(); 
    ~Book(); 
    // ... 
    friend std::istream& operator>>(std::istream& in, Book& book){ 
     Item& item = book; 
     return in >> item >> book.name; 
    } 
}; 

注意。

あなただけでfrom_streamメソッド実装した場合でも、容易に行うことができます:from_streamvirtualであることに

class Item 
{ 
protected: 
    int _sn; 
public: 
    Item(); 
    ~Item(); 
    // ... 
    virtual void from_stream(std::istream& in){ 
     in >> _sn; 
    } 
}; 

std::istream& operator>>(std::istream& in, Item& item){ 
    item.from_stream(in); 
    return in; 
} 

class Book 
    : public Item 
{ 
private: 
    std::string name; 
public: 
    Book(); 
    ~Book(); 
    // ... 
    void from_stream(std::istream& in){ 
     Item::from_stream(in); 
     in >> name; 
    } 
}; 

おかげで、あなたはoperator>>を再実装する必要はありません、それが自動的いると応じた正しい派生クラスに派遣します

1

次のような基本クラスのメソッド:

void Derived::foo(args) { 
    Base::foo(args); 
} 

// or 

class Derived : public Base { 

    int operator<<(int a) { 
     Base::operator<<(a); 
    } 
} 

Base(もっと直接的または間接的な基底クラスがあるかもしれないので、あなたがそれを指定する必要があります)、特定の基本クラスの名前です。

::が「範囲演算子」です。それは、Baseの範囲から関数operator<<を呼び出すことを意味します。


上記おそらく(@Xeoが指摘したように、感謝!)いくつかの時間は、この特定の演算子とこのような状況の場合には、オペレータが自由関数として定義されなければならないために有用であろう(このクラスのオブジェクトを最初のパラメータ(左のオペランド)として使用する場合は、メンバー関数としてoperator<<またはoperator>>と定義するだけであるため、メンバ関数ではありません。ストリームの文脈で<<>>の場合

は、従来、左のオペランドが流れているので、あなたはostreamのためのメンバ関数は、同様に仕事ができる(この演算子のための無料の機能を必要としていますが、変更する必要がありますostream、あなたはそれを試したくありません)。

+0

ここでは動作しません。演算子>>は基本クラスのメンバーではなく、自由な関数です。 – Xeo

+0

ああありがとう:)、ちょっと混乱しました。 – Kos

2

基本クラスで定義された演算子を派生型から再利用する場合は、派生宣言で​​これを追加してください:

using Base::operator>>;

2

だけで、いや、直接ではなく。 operator>>は、ストリームオブジェクトのメンバ関数でなければ意味がありません。通常のオブジェクトでは、自由な関数でなければなりません。それをメンバ関数として定義すると、メンバ関数であるクラスは事実上左のオペランドになり、他のパラメータは右のオペランドになります。メンバーである2つのオペランド形式を持つことはできません。

operator>>の多型の動作を得るには、operator>>の実装で仮想関数を使用することができます。

class Base { 
public: 
    /* ... */ 
    virtual void FromStream(std::istream& is); 
    /* ... */ 
}; 

class Derived : public Base { 
    /* ... */ 
    virtual void FromStream(std::istream& is); 
    /* ... */ 
}; 

std::istream& operator>>(std::istream& is, Base& base) { 
    base.FromStream(is); 
    return is; 
} 
関連する問題