2013-04-21 36 views
6

Mã này từ chối in các thông điệp thích hợp vào bảng điều khiển khi tôi chạy nó. Sử dụng con trỏ thay vì tham chiếu dường như hoạt động (-> thay vì.). Tôi mới đến OOP vì vậy tha thứ cho tôi nếu bạn thấy điều này vô lý.Gọi các chức năng ảo thông qua tham chiếu đến lớp cơ sở

#include <iostream> 

using namespace std; 

class instrument { 
public: 
    virtual void play(){} 
}; 

class drum : public instrument { 
public: 
    void play(){ 
     cout << "dum, dum" << endl; 
    } 
}; 

class piano : public instrument { 
public: 
    void play(){ 
     cout << "pling" << endl; 
    } 
}; 

int main(){ 
    instrument i; 
    piano p; 
    drum d; 

    instrument &pi = i; 
    pi.play(); // - 

    pi = p; 
    pi.play(); // pling 

    pi = d; 
    pi.play(); // dum, dum 
} 
+9

Bạn không thể thay đổi tham chiếu từ đối tượng mà tài liệu tham chiếu khi nó bị ràng buộc khi khởi tạo. Ngay bây giờ các toán tử gán nhiệm vụ của bạn (và kích hoạt [đối tượng cắt] (http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c/274634#274634) trong quá trình này). – WhozCraig

+4

Làm cho câu trả lời đó, đúng không? – jrok

+0

Một vấn đề phụ, nhưng bạn cần tạo một destructor ảo trong lớp cơ sở. –

Trả lời

15
instrument &pi = i; 

Ở đây bạn thực hiện pi tham khảo các instrument đối tượng i.

pi = p; 

Ở đây bạn được giao piano đối tượng p đến đối tượng được gọi bằng pi. Tham chiếu pi không được phục hồi đối tượng piano. Nó vẫn đề cập đến cùng một đối tượng instrument như trước đây. Nó chỉ là các nội dung khác nhau đã được gán cho nó bằng cách sử dụng toán tử gán mặc định được tạo ngầm định. (Trong trường hợp này, nhiệm vụ không có hiệu lực, nhưng gán một kiểu dẫn xuất cho một kiểu cơ sở thường dẫn đến việc cắt đối tượng.) Khi bạn gọi pi.play(), tham chiếu vẫn đề cập đến một đối tượng instrumentinstrument::play được thực thi.

Vấn đề là, trong khi bạn có thể nhận con trỏ trỏ tới một đối tượng khác của một loại khác, bạn không thể làm tương tự với tham chiếu. Nó luôn luôn chỉ vào cùng một đối tượng. Bạn có thể sửa mã của mình bằng cách sử dụng nhiều tham chiếu:

instrument &pi = i; 
pi.play(); // - 

instrument &pp = p; 
pp.play(); // pling 

instrument &pd = d; 
pd.play(); // dum, dum 
+1

Con trỏ có nhiều hơn một chút linh hoạt và linh hoạt hơn so với tài liệu tham khảo, phải không? – Venom

+0

@Venom no. cả hai đều có cách sử dụng của chúng –

+1

@Venom Chúng có thể linh hoạt hơn nếu bạn chỉ xem xét chức năng thô của chúng. Tuy nhiên, bạn không phải lúc nào cũng muốn sự linh hoạt đó. Trong thực tế, nó thậm chí có thể dẫn đến các vấn đề. Chọn loại thích hợp cho công việc. –

Các vấn đề liên quan