hời hợt vấn đề là bạn gọi một chức năng ảo chưa được biết (Các đối tượng được xây dựng từ cha mẹ sang con, do đó cũng là vtables). Trình biên dịch của bạn cảnh báo bạn về điều đó.
Bài báo thiết yếu, theo như tôi thấy, là bạn cố gắng sử dụng lại chức năng của kế thừa. Đây gần như luôn luôn là một ý tưởng tồi. Một vấn đề thiết kế, có thể nói :)
Về cơ bản, bạn hãy thử instantiating một phương pháp mô hình mẫu, để tách các gì từ khi: trước hết hãy đọc một số dữ liệu (một cách nào đó), sau đó xử lý nó (trong một số cách).
Điều này có thể sẽ hoạt động tốt hơn với tập hợp: cung cấp chức năng Xử lý cho phương thức Mẫu để được gọi vào đúng thời điểm. Có lẽ bạn thậm chí có thể làm tương tự cho chức năng Đọc.
Việc tổng hợp có thể được thực hiện theo hai cách:
- Sử dụng chức năng ảo (ví dụ:Runtime Binding)
- Sử dụng mẫu (tức là thời gian biên dịch Binding)
Ví dụ 1: runtime ràng buộc
class Data {};
class IReader { public: virtual Data read() = 0; };
class IProcessor { public: virtual void process(Data& d) = 0; };
class ReadNProcess {
public:
ReadNProcess(IReader& reader, IProcessor processor){
processor.process(reader.read());
}
};
Ví dụ 2: compiletime ràng buộc
template< typename Reader, typename Writer > // definitely could use concepts here :)
class ReadNProcess {
public:
ReadNProcess(Reader& r, Processor& p) {
p.process(r.read());
}
};
Đúng, nhưng hơi ngắn. Ít nhất bạn nên sao chép kết luận: "Những điều cần nhớ: Đừng gọi các chức năng ảo trong quá trình xây dựng hoặc hủy diệt, bởi vì các cuộc gọi như vậy sẽ không bao giờ đi đến một lớp được dẫn xuất nhiều hơn so với các hàm tạo hiện tại hay hàm hủy." – paercebal
Tuy nhiên, tôi thực sự nghĩ rằng bạn nên suy nghĩ hai lần trước khi trộn trong chức năng của thừa kế. IMHO, câu hỏi này cho thấy một dòng chảy thiết kế dưới bề mặt. – xtofl