Tôi thường sử dụng các lớp ảo thuần túy (giao diện) để giảm sự phụ thuộc giữa việc triển khai các lớp khác nhau trong dự án hiện tại của tôi. Nó không phải là bất thường đối với tôi thậm chí có phân cấp trong đó tôi có các lớp học ảo tinh khiết và không thuần túy mà mở rộng các lớp học ảo tinh khiết khác. Dưới đây là một ví dụ về một tình huống như vậy:Đây có phải là một quy ước tốt để hầu như kế thừa từ các lớp học ảo (giao diện) thuần túy không?
class Engine
{ /* Declares pure virtual methods only */ }
class RunnableEngine : public virtual Engine
{ /* Defines some of the methods declared in Engine */ }
class RenderingEngine : public virtual Engine
{ /* Declares additional pure virtual methods only */ }
class SimpleOpenGLRenderingEngine : public RunnableEngine,
public virtual RenderingEngine
{ /* Defines the methods declared in Engine and RenderingEngine (that are not
already taken care of by RunnableEngine) */ }
Cả RunnableEngine
và RenderingEngine
mở rộng Engine
hầu để các vấn đề kim cương không ảnh hưởng đến SimpleOpenGLRenderingEngine
.
Tôi muốn có một lập trường phòng ngừa chống lại vấn đề kim cương thay vì xử lý nó khi nó trở thành vấn đề, đặc biệt là vì tôi thích viết mã dễ sử dụng nhất có thể và tôi không muốn họ phải sửa đổi các lớp của tôi để họ có thể tạo ra các lớp thừa kế cụ thể nếu Bob muốn làm điều này:
class BobsRenderingEngine : public virtual RenderingEngine
{ /* Declares additional pure virtual methods only */ }
class BobsOpenGLRenderingEngine : public SimpleOpenGLRenderingEngine,
public BobsRenderingEngine
{ /* Defines the methods declared in BobsRenderingEngine */ }
này sẽ không thực hiện được nếu tôi đã không được thực hiện SimpleOpenGLRenderingEngine
mở rộng RenderingEngine
hầu. Tôi biết rằng xác suất của Bob muốn thực hiện việc này có thể rất thấp.
Vì vậy, tôi đã bắt đầu sử dụng quy ước bao giờ cũng mở rộng các lớp ảo thuần túy để đa thừa kế từ chúng không gây ra vấn đề về kim cương. Có lẽ điều này là do tôi đến từ Java và có xu hướng chỉ sử dụng thừa kế đơn với các lớp học ảo không thuần túy. Tôi chắc chắn nó có lẽ là quá mức cần thiết trong một số tình huống nhưng có bất kỳ nhược điểm nào khi sử dụng quy ước này không? Điều này có thể gây ra bất kỳ vấn đề với hiệu suất/chức năng, vv? Nếu không, tôi không thấy lý do không sử dụng quy ước, ngay cả khi nó có thể không cần đến cuối cùng.
Yup, hoàn thành quá mức cần thiết. Nó chỉ là một vấn đề kim cương thực khi bạn có nhiều * triển khai * để lựa chọn. Không phải là vấn đề với giao diện, nó không có bất kỳ triển khai nào. Thừa kế ảo là một băng hỗ trợ, bạn chỉ sử dụng nó khi lưng của bạn chống lại bức tường. –
@ HansPassant, tôi không đồng ý với bạn. Dimond vấn đề thường có thể xảy ra ngay cả với các lớp học ảo tinh khiết. Giả sử bạn có một giao diện, nói IA, và thực thi mặc định của nó 'AImpl: public virtual IA', sau đó sử dụng thừa kế ảo, bạn có thể định nghĩa một 'lớp B: public virtual IA, public AImpl'. Do đó B sẽ sử dụng IA của thực hiện AImpl. –
@kids_fok Yup, đó chính xác là nơi tôi gặp vấn đề. Vâng, tôi không chắc chắn bạn cần 'B' để mở rộng' IA' một cách rõ ràng trong ví dụ của bạn bởi ví dụ trong câu hỏi của tôi là tương tự. –