2013-06-20 61 views
5

Tôi có lớp B kế thừa từ A.Kiểm tra các loại đối tượng trong C++ 11

class A 
{ 
}; 

class B : public A 
{ 
}; 

Và tôi có ba đối tượng.

A* a = new A(); 
A* a2 = new B(); 
B* b = new B(); 

Tôi muốn nếu kiểm tra một là đối tượng của loại A, a2 là đối tượng của loại B (không A), và b là đối tượng của loại B.

tôi đã cố gắng gõ so sánh, nhưng nó không cho tôi câu trả lời đúng.

cout << (typeid(*a) == typeid(A)) << endl; // -> 1 
cout << (typeid(*a2) == typeid(A)) << endl; // -> 1 
cout << (typeid(*b) == typeid(A)) << endl; // -> 0 

cout << (typeid(*a) == typeid(B)) << endl; // -> 0 
cout << (typeid(*a2) == typeid(B)) << endl; // -> 0 
cout << (typeid(*b) == typeid(B)) << endl; // -> 1 

Tôi đã thử truyền động nhưng tôi đã gặp phải lỗi biên dịch.

B* derived = dynamic_cast<B*>(a); 
if (derived) { 
    cout << "a is B"; 
} 
derived = dynamic_cast<B*>(a2); 
if (derived) { 
    cout << "a2 is B"; 
} 
derived = dynamic_cast<B*>(b); 
if (derived) { 
    cout << "b is B"; 
} 

typename.cpp: In function 'int main(int, char**)': 
typename.cpp:27:36: error: cannot dynamic_cast 'a' (of type 'class A*') to type 'class B*' (source type is not polymorphic) 
    B* derived = dynamic_cast<B*>(a); 
            ^
typename.cpp:31:34: error: cannot dynamic_cast 'a2' (of type 'class A*') to type 'class B*' (source type is not polymorphic) 
    derived = dynamic_cast<B*>(a2); 

Tôi đã sử dụng phép đúc tĩnh nhưng tôi đã nhận được câu trả lời sai.

B* derived = static_cast<B*>(a); 
if (derived) { 
    cout << "a is B"; // -> YES 
} 
derived = static_cast<B*>(a2); 
if (derived) { 
    cout << "a2 is B"; // -> YES 
} 
derived = dynamic_cast<B*>(b); 
if (derived) { 
    cout << "b is B"; // -> YES 
} 

Làm cách nào để xác định đúng loại đối tượng trong C++11?

+0

'* a' thuộc loại' A' và '* b' thuộc loại' B' trên mỗi khai báo của chúng. –

+0

Truyền động sẽ chỉ hoạt động với ảo nhưng mã của bạn không có bất kỳ chức năng ảo nào. –

+0

Giải pháp tối thiểu tốt nhất tương tự như mã của bạn: http://coliru.stacked-crooked.com/view?id=7150bf0db7988cf1d2988aba99c72392-3b440a87a52fe2ae7c853c82f4c5144f – chris

Trả lời

10

Một số lớp có tính đa hình, một số là không đa hình.

Một lớp đa hình có một hoặc nhiều hàm ảo (có thể được kế thừa), một lớp không đa hình có hàm số không ảo.

A và B của bạn không đa hình.

Một phiên bản đa hình của A và B sẽ triển lãm hành vi mà bạn muốn:

#include <iostream> 
#include <typeinfo> 

using namespace std; 

struct A 
{ 
    virtual ~A() {}; // add virtual function 
}; 

class B : public A 
{ 
}; 

A* a = new A(); 
A* a2 = new B(); 
B* b = new B(); 

int main() 
{ 
    cout << (typeid(*a) == typeid(A)) << endl; // -> 1 
    cout << (typeid(*a2) == typeid(A)) << endl; // -> 0 <-- CHANGED 
    cout << (typeid(*b) == typeid(A)) << endl; // -> 0 

    cout << (typeid(*a) == typeid(B)) << endl; // -> 0 
    cout << (typeid(*a2) == typeid(B)) << endl; // -> 1 <-- CHANGED 
    cout << (typeid(*b) == typeid(B)) << endl; // -> 1 
} 

Instances của một cửa hàng lớp đa hình kiểu năng động của họ có nguồn gốc nhất đối tượng khi chạy.

(Trong ví dụ của bạn a2 là loại con trỏ-to-A, và được chỉ vào một đối tượng kiểu A, tuy nhiên đối tượng này chỉ là một cơ sở lớp subobject của đối tượng dervived nhất loại B. những gì bạn muốn nhận được là loại này có nguồn gốc hầu hết các đối tượng B khi truy vấn a2. Đối với điều này bạn cần một lớp đa hình.)

Đó là cách đa hình các lớp học hỗ trợ dynamic_casttypeid của đối tượng có nguồn gốc nhất (cũng như ảo chức năng công văn).

Các lớp không đa hình không có thông tin này, vì vậy chúng chỉ có thể báo cáo loại tĩnh được biết đến tại thời gian biên dịch. Các lớp không đa hình là các lớp đa hình nhỏ gọn và hiệu quả hơn. Đó là lý do tại sao không phải tất cả các lớp C++ đều đa hình. Ngôn ngữ lá nó lên đến các lập trình viên để chọn sự cân bằng giữa hiệu suất và chức năng. Ví dụ:

struct X { int x; }; 
struct Y : X {}; 
struct Z : Y {}; 

Trên hệ thống của tôi không đa hình Zsizeof(Z) == 4 bytes, giống như một int.

struct X { int x; virtual ~X() {}; }; 
struct Y : X {}; 
struct Z : Y {}; 

Bây giờ sau khi thực hiện Z đa hình, sizeof(Z) == 16 bytes.Vì vậy, một mảng Z bây giờ lớn hơn 300%, bởi vì mỗi cá thể Z phải lưu trữ thông tin kiểu của nó khi chạy.

+1

http://stackoverflow.com/questions/17221668/why-do-we-need-to -use-virtual-a-default-thay-of-virtual-a-in-c – prosseek

+2

@Sharth: Không, [điều đó không đúng] (http://stackoverflow.com/a/17222286/560648); bạn không nhận được nó trong trường hợp _either_. –

+0

@LightnessRacesinOrbit, @prosseek: Cảm ơn bạn đã sửa! Tôi đã nghĩ rằng đó là một trong những lý do chính cho trường hợp '= default'. –

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