2017-07-04 21 views
5

Tôi đã đọc ở nhiều nơi giao diện của Java có thể được mô phỏng 100% bằng cách sử dụng lớp trừu tượng của C++ với tất cả các phương thức ảo thuần túy.Chồng chéo giao diện giống như java trong C++

Tôi đang cố gắng để chuyển đổi đoạn mã này java:

interface A { 
    void a(); 
} 

interface B extends A { 
    void b(); 
} 

class C implements A { 
    public void a() { 
    } 
} 

class D extends C implements B { 
    public void b() { 
    } 
} 

D d = new D(); 
d.a(); 
d.b(); 

vào một cái gì đó như thế này trong C++:

class A { 
public: 
    virtual void a() const = 0; 
protected: 
    virtual ~A() { 
    } 
}; 

class B : public A { 
public: 
    virtual void b() const = 0; 
protected: 
    virtual ~B() { 
    } 
}; 

class C : public /*implements*/ A { 
public: 
    virtual void a() const override { 
    } 
}; 

class D : public /*extends*/ C, public /*implements*/ B { 
public: 
    virtual void b() const override { 
    } 
}; 

D d; 
d.a(); 
d.b(); 

nhưng không có gì khó khăn khi tôi cố gắng, tôi luôn luôn kết thúc với C++ phàn nàn về sự mơ hồ và/hoặc thiếu định nghĩa cơ thể.

Ý tưởng là tôi muốn lấy từ "C" có chứa một số mã chia sẻ cho tất cả các lớp (ở đây: "D" nhưng có nhiều hơn) và vẫn giữ lời hứa rằng "D" là 100% hoán đổi cho nhau bất kỳ lớp nào thực hiện "B" (bao gồm các phần từ "A").

Các lỗi tôi nhận được với C++ mã trên là:

../untitled1/main.cpp: In function ‘int main(int, char**)’: 
../untitled1/main.cpp:39:7: error: cannot declare variable ‘d’ to be of abstract type ‘D’ 
    D d; 
    ^
../untitled1/main.cpp:28:7: note: because the following virtual functions are pure within ‘D’: 
class D : public /*extends*/ C, public /*implements*/ B { 
    ^
../untitled1/main.cpp:7:18: note: virtual void A::a() const 
    virtual void a() const = 0; 
       ^
../untitled1/main.cpp:40:7: error: request for member ‘a’ is ambiguous 
    d.a(); 
    ^
../untitled1/main.cpp:7:18: note: candidates are: virtual void A::a() const 
    virtual void a() const = 0; 
       ^
../untitled1/main.cpp:23:18: note:     virtual void C::a() const 
    virtual void a() const override { 
       ^
+0

bạn có thể vui lòng cho chúng ta thấy một [Minimal, *** Toàn bộ ***, và kiểm chứng Ví dụ] (http: // stackoverflow.com/help/mcve) và bao gồm các lỗi * thực tế * mà bạn nhận được (sao chép, dán, hoàn chỉnh, đầy đủ và chưa chỉnh sửa)? –

+1

@Someprogrammerdude: đoạn mã * được * hoàn thành, tôi đoán tôi không phải cung cấp một hàm main(). Tôi đã thêm đầu ra trình biên dịch. –

+1

Bạn có thể gặp phải vấn đề * kim cương *. –

Trả lời

9

Đây là vấn đề được giải quyết bằng cách thừa kế ảo từ A.

class A { 
public: 
    virtual void a() const = 0; 
protected: 
    virtual ~A() { 
    } 
}; 

class B : public virtual A { 
public: 
    virtual void b() const = 0; 
protected: 
    virtual ~B() { 
    } 
}; 

class C : public virtual A { 
public: 
    virtual void a() const override { 
    } 
}; 

class D : public C, public B { 
public: 
    virtual void b() const override { 
    } 
}; 

Vấn đề là trừ khi bạn chỉ định rằng cả hai CB cần chia sẻ một A sub-object (tất cả các lớp học có nguồn gốc chứa các căn cứ của họ như phụ đối tượng), hai đối tượng con bạn nhận được từ thừa kế cả BC sẽ không có liên quan.

Trong sơ đồ ban đầu, triển khai được cung cấp bởi C cho thành viên ảo thuần túy trong A không được coi là triển khai cho cùng chức năng được yêu cầu bởi A trong B.

Kể từ bây giờ chỉ có một đối tượng phụ A, vấn đề này biến mất. Nhưng lưu ý rằng thừa kế ảo không phải là không có giá. Vì vậy, hãy suy nghĩ nếu bạn thực sự muốn đi với một thiết kế như vậy.

+1

SO tốt nhất của nó. Tôi đã thử ít nhất hai kế hoạch thừa kế ảo khác nhau nhưng vì tôi chỉ có ý tưởng mơ hồ về cách thức hoạt động của nó mà tôi đã thất bại. Cảm ơn bạn về mã & giải thích. –

+0

Bạn đã giải quyết vấn đề kim cương – Steephen

+0

@Steephen - Tôi dám nói rằng tôi không xứng đáng nhận được tín dụng để giải quyết nó. Đó là ủy ban thiết kế ngôn ngữ đã đưa ra cơ chế này :) – StoryTeller

0

Tất cả những gì bạn cần là thi hành một() trong lớp D:

class A { 
public: 
    virtual void a() const = 0; 
protected: 
    virtual ~A() { 
    } 
}; 

class B : public A { 
public: 
    virtual void b() const = 0; 
protected: 
    virtual ~B() { 
    } 
}; 

class C : public /*implements*/ A { 
public: 
    virtual void a() const override { 
    } 
}; 

class D : public /*extends*/ C, public /*implements*/ B { 
public: 
    void b() const override { 
    } 
    void a() const { 
     C::a(); 
    } 
}; 




int main() 
{ 
    D d; 
    d.a(); 
    d.b(); 
    return 0; 
} 
+1

Điều này sẽ không thực sự giúp chia sẻ mã chung trong một lớp (C), đúng không. Hãy tưởng tượng bạn có 20 lớp kế thừa như D. –

+0

Vì vậy, cố gắng lớp thay đổi D để một cái gì đó như thế: lớp D: public/* mở rộng */C, công/* thực */B { \t công cộng: \t \t trống b() ghi đè const { \t \t} \t \t void a() const { \t \t \t C :: a(); \t \t} \t}; –

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