2010-06-30 43 views
18

Tôi có một cái gì đó như thế (giản thể)C++ chức năng ghi đè ảo cùng tên

class A 
{ 
    public: 
    virtual void Function() = 0; 
}; 

class B 
{ 
    public: 
    virtual void Function() = 0; 
}; 

class Impl : public A , public B 
{ 
    public: 
     ???? 
}; 

Làm thế nào tôi có thể thực hiện các chức năng() cho A và Function() cho B? Visual C++ cho phép bạn chỉ xác định hàm nội tuyến cụ thể (nghĩa là không có trong tệp cpp), nhưng tôi cho rằng đó là phần mở rộng. GCC phàn nàn về điều này. Có cách nào C++ chuẩn để báo cho trình biên dịch biết hàm tôi muốn ghi đè không?

(visual C++ 2008)

class Impl : public A , public B 
{ 
    public: 
    void A::Function() { cout << "A::Function" << endl; } 
    void B::Function() { cout << "B::Function" << endl; } 
}; 

Cảm ơn bạn!

+0

cũng vậy, cuối cùng tôi đã nhận ra cách QueryInterface xảy ra để hoạt động khi triển khai nhiều giao diện COM! :) – QbProg

Trả lời

30

Bạn không thể sử dụng tên đủ điều kiện tại đó. Tôi bạn viết void Function() { ... } bạn đang ghi đè cả hai chức năng. Herb Sutter hiển thị how it can be solved.

Một tùy chọn khác là đổi tên các chức năng đó, vì rõ ràng chúng làm điều gì đó khác (nếu không tôi không thấy vấn đề ghi đè cả hai với hành vi giống nhau).

+0

cảm ơn bạn đã liên kết :) – QbProg

-1

Nếu A và B là giao diện, thì tôi sẽ sử dụng đạo hàm ảo để "nối" chúng (làm cho chúng trùng lặp). Nếu bạn cần triển khai khác nhau cho Function nếu được gọi thông qua con trỏ đến A hoặc đến B thì tôi thực sự khuyên bạn nên chọn một thiết kế khác. Điều đó sẽ làm tổn thương khác.

Impl "bắt nguồn từ" AB nghĩa Impl "là một" AB. Tôi cho rằng bạn không có ý đó.

Impl "thực hiện giao diện" AB nghĩa Impl "cư xử như" AB. thì giao diện tương tự cũng có nghĩa là hành vi tương tự.

Trong cả hai trường hợp có hành vi khác nhau theo loại con trỏ được sử dụng sẽ là "tâm thần phân liệt" và chắc chắn là một tình huống cần tránh.

+2

không có kim cương ở đây. Chỉ có xung đột tên. A và B có thể đến từ các thư viện khác nhau. –

+0

@ Có, đó là thuật ngữ xấu, xung đột không gian tên là thích hợp. – jdehaan

+1

Làm thế nào ảo dẫn xuất giúp đỡ ở đây? – curiousguy

2

Là một workaround, hãy thử

struct Impl_A : A 
{ 
    void Function() { cout << "A::Function" << endl; } 
}; 


struct Impl_B : B 
{ 
    void Function() { cout << "B::function" << endl; } 
}; 

struct Impl : Impl_A, Impl_B {}; 
1

Tôi có thể đề nghị một cách khác để giải quyết vấn đề này. Bạn có thể thêm trình bao bọc Typed thay đổi chữ ký Function bằng cách thêm thông số giả. Vì vậy, bạn có thể phân biệt các phương pháp trong việc thực hiện của bạn.

class A { 
public: 
    virtual void Function() = 0; 
    virtual ~A() = default; 
}; 

class B { 
public: 
    virtual void Function() = 0; 
    virtual ~B() = default; 
}; 

template<typename T> 
class Typed : public T { 
public: 
    virtual void Function(T* dummy) = 0; 
    void Function() override { 
    Function(nullptr); 
    } 
}; 

class Impl : public Typed<A>, public Typed<B> { 
public: 
    void Function(A* dummy) override { 
    std::cerr << "implements A::Function()" << std::endl; 
    } 
    void Function(B* dummy) override { 
    std::cerr << "implements B::Function()" << std::endl; 
    } 
}; 

Lợi ích của giải pháp như vậy là tất cả việc triển khai được đặt trong một lớp.

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