2011-12-31 66 views
2

我有以下問題:假設類Item包含產品的序列號, 和Book類是Item,它繼承了類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,因爲左邊是你的類類型的不行。其次,lhs也必須是非const引用(因爲流在提取時會改變狀態),第二個參數也是如此(您需要改變狀態,它必須是非const的)。考慮到這一點,這裏的運營商應該如何看待:

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

請注意,我改變了你的C風格的字符串處理(char name[20] + strncpy)爲std::string,這是你應該用C做什麼++。

它可以,如果你只是實現from_stream方法來完成更簡單:

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

由於from_streamvirtual,你永遠不需要重新實現operator>>,它會自動分派到正確的派生類取決於與它被稱爲:

int main(){ 
    Item item; 
    Book book; 

    std::cin >> item; // calls operator>>(std::cin, item), them item.from_stream(std::cin) 

    std::cin >> book; // calls operator>>(std::cin, book), converting book to its baseclass Item 
        // then calls Book::from_stream(std::cin), which in turn calls Item::from_stream(std::cin) 

} 
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

這不會在這裏工作,'operator >>'不是基類成員,而是一個自由函數。 – Xeo 2011-12-31 11:26:56

+0

哦謝謝:),有點困惑。 – Kos 2011-12-31 11:35:48

2

如果你想重新使用派生的基類中定義的運算符,只需在派生聲明中添加它:

using Base::operator>>;

2

簡單地說,不,不是直接。 operator>>只能是流對象的成員函數。對於普通的對象,它應該是一個自由函數。如果將其定義爲成員函數,那麼它是成員函數的類實際上成爲左操作數,而另一個參數成爲右操作數。你不能有一個成員的兩個操作數形式。

可以在實現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; 
}