2011-01-03 34 views
23

Trong C++, tôi muốn biết loại thực tế của đối tượng là từ cùng một lớp, không phải cùng một lớp hoặc một lớp có nguồn gốc. Điều này tương tự như mã C# sau:Loại kiểm tra trong C++

Class Base 
{ 
} 

Class Child:Base 
{ 
} 

Base childObject = new Child(); 

If (childObject.GetType() == typeof(Child)) 
{ 
// do some code 
} 

Cảm ơn!

+0

Loại 'childObject' là gì? Không có cách chung để làm điều này trong C++ bởi vì, khi chạy, khái niệm về kiểu không tồn tại. –

+0

Ok, tôi sẽ chỉnh sửa câu hỏi – Homam

+2

Mặc dù bạn không nói gì về childObject.GetType(), tuy nhiên mã này là khủng khiếp, bởi vì nó chi nhánh trên so sánh kiểu. Đó là những gì OOP được cho là để loại bỏ. –

Trả lời

48

Có hai cách để bạn có thể thực hiện việc này. Đầu tiên, bạn có thể sử dụng toán tử typeid, trả về cấu trúc type_info chứa thông tin về loại đối tượng. Ví dụ:

Base* ptr = /* ... */ 
if (typeid(*ptr) == typeid(DerivedType)) { 
    /* ... ptr points to a DerivedType ... */ 
} 

Lưu ý rằng bạn phải sử dụng typeid(*ptr) và không phải typeid(ptr) tại đây. Nếu bạn sử dụng typeid(ptr), thì bạn sẽ lấy lại đối tượng type_info cho Base*, vì con trỏ có loại Base* bất kể nó trỏ đến điểm gì.

Một điểm quan trọng cần lưu ý là điều này sẽ kiểm tra xem những gì ptr điểm là chính xácDerivedType. Nếu ptr chỉ vào một đối tượng thuộc loại có nguồn gốc từ DerivedType (có thể là EvenMoreDerivedType), mã này sẽ không hoạt động chính xác.

Một cách khác để kiểm tra xem bạn đang chỉ vào một đối tượng thuộc loại nào đó mạnh hơn một chút là sử dụng toán tử dynamic_cast. dynamic_cast thực hiện một kiểu chữ được kiểm tra ở thời gian chạy sẽ mang lại một con trỏ hợp lệ nếu diễn viên thành công và NULL nếu không. Ví dụ:

Base* ptr = /* ... */; 
DerivedType* derived = dynamic_cast<DerivedType*>(ptr); 
if (derived) { 
    /* ... points to a DerivedType ... */ 
} 

này có lợi thế thêm rằng nếu ptr điểm tại một cái gì đó giống như một EvenMoreDerivedType, các diễn viên sẽ vẫn thành công vì EvenMoreDerivedType thừa hưởng từ DerivedType.

Như một ý nghĩ cuối cùng, bạn đôi khi thấy mã như thế này:

Base* ptr = /* ... */ 
if (DerivedType* derived = dynamic_cast<DerivedType*>(ptr)) { 
    /* ... points to a DerivedType ... */ 
} 

này tại địa phương phạm vi con trỏ derived cho cơ thể của báo cáo kết quả if và sử dụng thực tế là các giá trị khác không đánh giá để true trong C++. Cá nhân tôi thấy điều này dễ đọc hơn và ít bị lỗi hơn, nhưng bằng mọi cách đi với những gì dễ dàng nhất cho bạn.

Hy vọng điều này sẽ hữu ích!

+0

Ông muốn biết nếu đối tượng là một cơ sở, không phải nếu nó là một lớp dẫn xuất. – Puppy

+0

Ah ... Tôi bị nhầm lẫn bởi mã mẫu của anh ấy, điều này đang kiểm tra xem con trỏ có đang trỏ vào một kiểu con không. Một điểm hợp lệ. – templatetypedef

2

Bạn có thể sử dụng typeid().

if (typeid(childObject) == typeid(ChildType)) { 
} 

Nếu điều này trả về đúng thì bạn biết đó là lớp con.

+2

Bạn sẽ cần phải chắc chắn rằng bạn biên dịch với nhận dạng loại thời gian chạy (RTTI) được kích hoạt quá. –

+3

Lưu ý rằng ** chỉ hoạt động ** nếu mục được so sánh có vtbl. –

+0

@Billy: Đó là sự thật - nhưng ai không cung cấp cho lớp cơ sở của họ destructors ảo? Các chức năng ảo thực tế là điểm kế thừa. Nó không phải là không hợp lý để mong đợi nó. – Puppy

9

Trong khi câu trả lời của DeadMG là chính xác (tôi đã sử dụng nhiều lần nhiều lần), tôi nghĩ tôi sẽ ném điều này ra ngoài cho hậu thế. Cách "đúng" để thực hiện việc này, từ chế độ xem hướng đối tượng là:

Class Base 
{ 
    virtual void something() { 
     // probably a no-op, but maybe some default stuff 
    } 
} 

Class Child : public Base 
{ 
    virtual void something() { 
     // do your child-specific code here 
    } 
} 

Base* childObject = new Child(); 
childObject->something(); // does the right thing 
+0

Tôi thứ hai câu trả lời này. Câu trả lời của DeadMG mặc dù chính xác có thể không phải là một thực hành lập trình tốt ..! –

+0

Tính năng này hoạt động tốt khi bạn muốn thực hiện nội dung nào đó với đối tượng. Mặt khác, khi bạn muốn xử lý các đối tượng tùy thuộc vào loại của chúng, nó trở nên phức tạp và bất tiện (với tất cả các công văn đôi và khách truy cập) –

+0

@ 7vies, true, nhưng phổ biến nhất, phương pháp ảo này sẽ làm việc tốt nhất, và dễ bảo trì nhất. Có những lúc dynamic_cast hoặc typeid là cách tiếp cận đúng, nhưng đó là những dịp hiếm hơn. – Tim