2012-01-06 31 views
7

Điều tôi muốn làm là phát triển hai lớp cơ sở khác nhau mà không nên được kế thừa cùng nhau trong một lớp dẫn xuất. Có cách nào tôi có thể thực thi điều này tại thời gian biên dịch?Có thể ngăn chặn nhiều thừa kế các lớp cơ sở cụ thể tại thời gian biên dịch không?

class Base1 {}; 
class Base2 {}; 
class Derived1 : public Base1 {} // OK! 
class Derived2 : public Base2, public Other {} // OK! 
class Derived3 : public Base1, Base2 {} // Can I force the compiler to complain? 

Derived1 d1; // OK! 
Derived2 d2; // OK! 
Derived3 d3; // Or can I force the compiler to complain here? 

Tôi biết rằng documentation là một ý tưởng hay, chỉ cần tự hỏi nếu có thể.

+2

Tôi nghĩ rằng việc xây dựng tư nhân sẽ thực hiện thủ thuật. Nhưng nó cũng sẽ vô hiệu hóa trường hợp 'Derived2'. – littleadv

+0

Không đủ để viết "Đừng làm điều này!" trong tài liệu? –

Trả lời

8

Bạn đang thiết lập một số loại khớp nối giữa Base1 và Base2 ở chỗ chúng không thể bắt nguồn từ cả hai.

Bạn có thể làm cho cả hai bắt nguồn từ Base0 trong trường hợp nếu bạn lấy được Base1 và Base2, bạn sẽ nhận được nhiều kim cương thừa kế để bạn gặp lỗi trình biên dịch giả sử bạn không sử dụng thừa kế ảo và bạn không giải quyết .

Điều đó có thể giải quyết được sự cố của bạn nhưng tôi thắc mắc tại sao bạn đang cố thực hiện việc này.

(Base0 không phải là một lớp hoàn toàn trống vì phải có thứ gì đó mơ hồ khiến trình biên dịch phàn nàn. Và tất nhiên bạn có thể giải quyết nó để nó không ngăn cản bạn phát sinh từ cả hai, chỉ là nó sẽ tạo ra trình biên dịch yêu cầu "lỗi" nếu bạn làm điều đó do nhầm lẫn).

Một ví dụ có thể là:

class Base0 
{ 
    protected: 
    virtual ~Base0(){}; 
    virtual void abstractMethod() const = 0; 
}; 

class Base1 : public Base0 
{ 
    protected: 
    virtual void abstractMethod() const; 

    // rest of Base1 
}; 

class Base2 : public Base0 
{ 
    protected: 
    virtual void abstractMethod() const; 

    // rest of Base1 
}; 

class Derived : public Base1, public Base2 
{ 
    // if I don't resolve abstractMethod it is ambiguous and the compiler will let me know 
}; 
+0

+1 cho "Tôi hỏi tại sao bạn đang cố gắng làm điều này": bất kỳ lập trình nào cảm thấy cần phải đi nhiều cách thừa kế nên biết hậu quả – stijn

+1

xin vui lòng đưa ra một ví dụ làm thế nào bạn sẽ làm cho một lỗi trình biên dịch hiển thị với một Base0 cơ sở chung lớp học? dường như không rõ ràng. chỉ cho phép Base1 và Base2 kế thừa từ Base0 không đưa ra bất kỳ lỗi nào cả. – codeling

+0

@nyalathotep Đó là không có lý do để ngẫu nhiên downvote một câu trả lời từ một câu hỏi đó là 2 tuổi mà người dùng đã chấp nhận. Chỉ cần có một Base0 rỗng sẽ không gây ra vấn đề gì, cần phải có thứ gì đó được nhân thừa kế thừa gây ra xung đột. – CashCow

0

Một vấn đề thú vị. Tôi đã tìm thấy một giải pháp phù hợp với Trình biên dịch Tối ưu hóa Microsoft (R) C/C++ Phiên bản 18.00.31101 cho x64:

#include <iostream> 
#include <assert.h> 
using namespace std; 

class SuperBase { 
public: 
SuperBase():count(0) { 
    cout << "SuperBase constructor..." << endl; 
} 
~SuperBase() {} 
protected: 
int count; 
}; 
class Base1:virtual SuperBase 
{ 
public: 
Base1() 
{ 
    SuperBase::count++; 
    assert(SuperBase::count==1); 
    cout << "Base1 constructor..." << endl; 
} 

~Base1() 
{ 
    cout << "Base1 Destructor..." << endl; 
} 
}; 

class Base2:virtual SuperBase 
{ 
public: 
Base2() 
{ 
    SuperBase::count++; 
    assert(SuperBase::count==1); 
    cout << "Base2 constructor..." << endl; 
} 

~Base2() 
{ 
    cout << "Base2 Destructor..." << endl; 
} 
}; 

class Derived : public Base1, public Base2 
{ 
public: 
    Derived() 
    { 
    cout << "Derived constructor...." << endl; 
    } 
    ~Derived() 
    { 
    cout << "Derived Destructor..." << endl; 
    } 
}; 

class Derived1 : public Base1 
{ 
public: 
    Derived1() 
    { 
    cout << "Derived1 constructor...." << endl; 
    } 
    ~Derived1() 
    { 
    cout << "Derived1 Destructor..." << endl; 
    } 
}; 
class Derived2 : public Base2 
{ 
public: 
    Derived2() 
    { 
    cout << "Derived2 constructor...." << endl; 
    } 
    ~Derived2() 
    { 
    cout << "Derived2 Destructor..." << endl; 
    } 
}; 



int main() 
{ 
    cout << "Hello World" << endl; 
    Base1 b1; Base2 b2; 
    Derived1 d1; 
    Derived2 d2; 
    // Derived d; // - uncomment this line to get run-time error. 

    return 0; 
} 
+0

Tôi nghĩ rằng người dùng muốn có một lỗi biên dịch thời gian không phải là một xác nhận thời gian chạy. – CashCow

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