2013-08-10 60 views
5

Tôi đã ba lớp cấu trúc như thế này:Việc khắc phục C++ Nhiều Inheritance nhập nhằng Gọi

#include <iostream> 
using namespace std; 

class Keyword 
{ 
    public: 
     virtual float GetValue() = 0; 
}; 

class CharacterKeyword : public Keyword 
{ 
    public: 
     virtual float GetValue(){return _value;} 
    private: 
     float _value; 
}; 

class MeasurementKeyword : public Keyword 
{ 
    public: 
     virtual float GetValue(){return _value;} 
    private: 
     float _value; 
}; 

class AddressType : public CharacterKeyword, public MeasurementKeyword 
{ 

    private: 
     float address; 
     float addresExt; 
}; 

int main() 
{ 
    AddressType *a = new AddressType(); 
    a->GetValue(); 
    return 0; 
} 

Tôi nhận được những điều sau đây:

In function ‘int main()’:
error: request for member ‘GetValue’ is ambiguous
error: candidates are: virtual float Keyword::GetValue()
error: virtual float MeasurementKeyword::GetValue()
error: virtual float CharacterKeyword::GetValue()

Tôi đã thực hiện một số đọc vào nhiều thừa kế và tôi biết rằng nó có rất nhiều cạm bẫy - đây là một trong số chúng. Tôi cần cấu trúc lớp của tôi để được như thế này vì vậy tôi đã tự hỏi nếu có một cách mà tôi có thể sửa lỗi này bằng cách sử dụng mẫu?

Cập nhật
Sau khi đọc bình luận của bạn, suy nghĩ ban đầu của tôi là có lẽ tôi chỉ có thể phân định giữa một AddressType đó là một CharacterKeyword và một AddressType đó là một MeasurementKeyword bởi templating các AddressType. Và sử dụng nó như vậy trong mã cập nhật. HOẶC Tôi chỉ có thể chỉ định không gian tên của thành viên mà tôi muốn. Kể từ khi các cách templated chưa được đề cập đến như là một câu trả lời, nó là một sửa chữa xấu? Tôi có nên chỉ định không gian tên của thành viên tôi muốn không?

template <class T> 
class AddressType : public T 
{ 

    private: 
     float address; 
     float addresExt; 
}; 

int main() 
{ 
    AddressType<MeasurementKeyword> *a = new AddressType<MeasurementKeyword>(); 
    a->GetValue(); 
    return 0; 
} 
+1

Phụ thuộc vào cách bạn muốn để sửa lỗi này .. những gì bạn muốn xảy ra ở đây? –

+0

@KarthikT đó là lý do tại sao tôi đã cho anh ta cả hai cách;) – aaronman

+0

@aaronman Yup, không làm hỏng giải pháp của bạn, nhưng không chắc chắn những gì anh ta muốn hoàn thành với các mẫu .. –

Trả lời

13

Điều này là do một số diamond inheritance pattern, để giải quyết lỗi, bạn có thể chỉ định không gian tên cụ thể mà bạn muốn thành viên.

paddressType->MeasurementKeyword::GetValue() 

hoặc

paddressType->CharacterKeyword::GetValue() 

  1. Về cơ bản lớp AddressType của bạn có quyền truy cập vào các GetValue thành viên từ cả lớp nó được thừa hưởng từ và không thể chọn một (gọi là mơ hồ).
  2. scope resolution operator (::) giúp chỉ định bạn thực sự muốn cái nào.
  3. Bạn đã không nói những gì bạn thực sự muốn mã này để làm như vậy tôi sẽ chỉ nói rằng mô hình thừa kế thường phức tạp không có lợi cho việc tạo mã có thể đọc được, suy nghĩ lại những gì bạn thực sự muốn.
3

Nói chung, khi bạn chạy vào deadly diamond of death đó là dấu hiệu cho thấy bạn nên suy nghĩ lại về thiết kế của mình. Tuy nhiên, nếu bạn hoàn toàn không thể tránh tình huống này, C++ cung cấp giải pháp dưới dạng virtual inheritance. Sự thừa kế ảo giải quyết một số "sự mơ hồ về kim cương", nhưng nó cũng rất khó khăn. Ví dụ, bạn phải gọi một cách rõ ràng các hàm tạo non-default của cha mẹ trong hàm tạo của lớp dẫn xuất.

Một lần nữa, cách tốt nhất là tránh kim cương ngay từ đầu. Tôi đã được lập trình trong C++ trong nhiều năm, và cho đến nay tôi chưa bao giờ gặp vấn đề này trong mã của tôi.

+0

"bạn phải gọi một cách rõ ràng các hàm tạo của cha mẹ trong hàm tạo của lớp dẫn xuất". Bạn có nghĩa là các lớp cơ sở ảo được khởi tạo trong lớp có nguồn gốc cao nhất? Nếu có các ctors mặc định trong lớp cơ sở ảo, bạn không cần phải gọi chúng một cách rõ ràng. – dyp

+0

ảo không giải quyết được vấn đề này, cuộc gọi vẫn còn mơ hồ, tôi đồng ý với phần còn lại – aaronman

+0

@DyP Có. Tôi có nghĩa là bạn cần phải đề cập đến lớp học của cha mẹ. – Dima

2

xác định AddressType như thế này:

class AddressType : public CharacterKeyword, public MeasurementKeyword 
{ 
public: 
    using MeasurementKeyword::GetValue; 
private: 
    float address; 
    float addresExt; 
}; 
Các vấn đề liên quan