2009-02-26 55 views
5

Tôi có một lớp cơ sở và một lớp dẫn xuất. Mỗi lớp có tệp .h và tệp .cpp.dynamic_cast không thành công

Tôi đang làm dynamic_cast của đối tượng lớp cơ sở để các lớp có nguồn gốc trong đoạn mã sau:

h file:

class Base 
{ 
    public: 
    Base(); 
    virtual ~Base(); 
}; 

class Derived : public Base 
{ 
    public: 
    Derived(){}; 
    void foo(); 
}; 

class Another 
{ 
    public: 
    Another(){}; 
    void bar(Base* pointerToBaseObject); 
}; 

file cpp:

Base::Base() 
{ 
    //do something.... 
} 
Base::~Base() 
{ 
    //do something.... 
} 
void Derived::foo() 
{ 
    Another a; 
    a.bar(this); 
} 
void Another::bar(Base* pointerToBaseObject) 
{ 
    dynamic_cast<Derived*>(pointerToBaseObject) 
} 

Từ một số lý do kỳ lạ , đúc không thành công (trả về NULL). Tuy nhiên, quá trình truyền thành công nếu tôi di chuyển việc triển khai hàm tạo của lớp Derived từ .h sang tệp .cpp.

Điều gì có thể gây ra?

Trình biên dịch là gcc 3.1, trên Linux-SUSE. BTW, tôi thấy hành vi này chỉ trên nền tảng này, và cùng một mã hoạt động tốt trong Visual Studio.

+0

có lẽ đó là một lỗi với gcc 3.1? hãy thử tùy chọn "-fdump-class-hierarchy" và xem nó có tạo ra vtable cho hai lớp của bạn –

Trả lời

5

Mã, như đã đăng, không được thất bại, miễn là bạn có chức năng ảo trong lớp cơ sở (như đã được chỉ ra).

Nhưng tôi tin rằng mọi trình biên dịch hiện tại sẽ tạo ra một loại "Lớp cơ sở không phải là đa hình" nếu bạn không có, do đó có thể sẽ không có vấn đề gì.

Điều duy nhất tôi có thể nghĩ đến là do một số lỗi lạ, mọi thứ được inlined và không có vtable được tạo ra. Nhưng nếu bạn đặt hàm tạo trong tệp C++, trình biên dịch quyết định không nội tuyến mọi thứ, kích hoạt việc tạo vtable, khiến cho dàn diễn viên của bạn hoạt động.

Nhưng đây là phỏng đoán rất hoang dã, và tôi không nghĩ rằng bất kỳ trình biên dịch sẽ có một sai lầm trong nó (?)

Nếu bạn muốn có một câu trả lời rõ ràng, gửi mã hơn. Và trình biên dịch/nền tảng được sử dụng.

EDIT: Thấy mã cập nhật

Tôi nghĩ bạn nên ít nhất rút ra nguồn gốc từ cơ sở;) (Tôi cho rằng đó là một lỗi đánh máy)

Nhưng sau khi nhìn thấy mã này, điều duy nhất tôi có thể nghĩ đến là gcc (sai) inlines tất cả mọi thứ và không tạo ra một vtable cho Derived. Đối với những gì nó có giá trị, điều này chạy tốt biên soạn với gcc 4.0

3.1 là hơn 7 tuổi bây giờ ... nếu có bất kỳ khả năng để nâng cấp tôi muốn đi cho nó.

7

Bạn có bất kỳ chức năng ảo nào trong Base không? Nó sẽ không hoạt động nếu không. Nếu không có gì khác, làm cho dtor của nó ảo.

Không biết liệu nó đã được yêu cầu bởi người khác đã xóa câu trả lời của mình, nhưng tôi tin rằng đó là một cái gì đó khác nhau: Bạn đang làm dynamic_cast từ constructor của các căn cứ? Nếu vậy, điều đó sẽ không hoạt động. Trình biên dịch sẽ nghĩ rằng Base là kiểu được sinh ra nhiều nhất, tương tự như khi bạn gọi một hàm ảo và nó kết thúc bằng việc gọi phiên bản của Base.

+0

Tôi có các hàm ảo trong Base hay không. –

3

Làm cho trình phá hủy ảo và đặt nó (hoặc ít nhất một phương pháp ảo) trong tệp .cpp.

Một số trình biên dịch (đọc: gcc) tìm kiếm phần thân phương thức ảo không nội tuyến đầu tiên và sử dụng nó để quyết định vị trí đặt bảng phương thức ảo.Nếu bạn không có bất kỳ phương thức ảo nào với các phần tử trong tệp .cpp, thì bảng phương thức ảo không được tạo.

Bạn phải có ít nhất một phương pháp ảo để dynamic_cast hoạt động. Dynamic cast sử dụng bảng để tìm ra thông tin kiểu và không có bảng nào được tạo nếu không có phương thức ảo nào.

Nếu bạn có một lớp mà bạn mong muốn được phân lớp và nó có một destructor hoặc nếu lớp có bất kỳ biến mẫu là lớp với destructors, sau đó bạn sẽ thực sự muốn làm cho destructor của bạn ảo (ngay cả khi nó có một cơ thể trống rỗng). Nếu không dọn dẹp bạn mong đợi sẽ không xảy ra đối với các thể hiện lớp con.

0

Bạn đang làm điều này trong Visual C++? Tôi nghĩ rằng bạn sử dụng để có cho phép thông tin kiểu thời gian chạy (RTTI) trong thiết lập trình biên dịch để làm việc này.

Xin đừng làm tôi bực mình nếu tôi đã sai. Đã lâu rồi kể từ khi tôi sử dụng C++ !!!

0

Khi xem mã của bạn, tôi không thấy bất kỳ thừa kế nào. Bạn đã quên làm điều đó chưa? Có nguồn gốc từ bất cứ thứ gì.

0

Trong mã bạn đã đăng Có nguồn gốc không có nguồn gốc từ Cơ sở.

Edit: FYI, mã sửa đổi hoạt động tốt với g ++ 3.4.5

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