2010-10-05 21 views
6

Mã dưới đây giải thích vấn đề. Điền vào same_sub_class để phát hiện nếu hai con trỏ tới lớp cơ sở ảo A thực tế là lớp cụ thể.Trong C++, hãy kiểm tra xem hai trường hợp của một lớp cơ sở có thuộc cùng một lớp con không

struct A { 
    ... 
}: 

struct B : public A { 
    ... 
}: 

struct C : public A { 
    ... 
} 


bool same_sub_class(A * a1, A * a2){ 
    // Fill this in to return true if a1 and a2 are 
    // of the same concrete class 
} 

EDIT:

Như tôi đã nhìn vào ứng dụng của tôi, tôi cần cái gì đó hơi khác biệt so với ở trên. Tôi cần để có thể nhóm các trường hợp theo type_id của họ.

FYI. Tôi có một hệ thống algerbra tượng trưng nhỏ để thao tác điều quan trọng là phải biết loại lớp đôi khi để phân loại và sắp xếp lại các biểu thức.

Vì vậy, hãy cho một vectơ con trỏ ví dụ cách nhóm chúng theo type_id của chúng. Tôi sẽ cần phải có khả năng băm type_id hoặc tạo ra một số nguyên duy nhất cho mỗi lớp.

+1

âm thanh như những gì bạn thực sự cần là một int tĩnh trên mỗi lớp để sắp xếp theo? –

Trả lời

17

Nếu bạn có thể sử dụng RTTI,

typeid(*a1) == typeid(*a2) 

Tôi nghĩ bạn cũng cần phải

#include <typeinfo> 

Và bạn phải có một hàm ảo trong lớp học của bạn để các vtable tồn tại - một destructor nên làm tốt.

CẬP NHẬT:

Tôi không chắc tôi hoàn toàn hiểu những gì yêu cầu của bạn là dành cho nhóm, nhưng bạn có thể thử (Bạn có cần một số loại trật tự xác định gì nên xảy ra với phụ lớp con?) sử dụng value trở về từ các nhà điều hành typeid cho một trong hai:

  • Hash chuỗi trở về từ typeid(*ptr).name()
  • sử dụng typeid(*a1).before(typeid(*a2)) như một tiêu chí đặt hàng. Tuy nhiên, điều này không có bất kỳ sự xác định nào giữa các lần chạy.

Nói chung khi xem xét RTTI, bạn nên xem liệu có thể thực hiện bất kỳ điều nào trong số này tốt hơn bằng cách sử dụng các hàm ảo được chế tác tốt (ví dụ: double dispatch). Tôi thực sự không thể nói nếu có một sự thay thế tốt trong trường hợp của bạn mặc dù, vì tôi không hiểu cụ thể.

+1

Bạn cũng cần ghi nhớ ''. –

+0

Nhưng 'A' phải được đa hình không ?? – liaK

+2

@liaK, có, lớp cơ sở phải có ít nhất một hàm ảo. – avakar

6
typeid(*a1) == typeid(*a2) 

Lưu ý điều quan trọng là điều quan trọng.

+0

Đồng thời, tất nhiên. –

2

Bạn có thể làm Loại số nhận dạng riêng của bạn:

struct A{ 
... 
protected: 
enum TypeTag{B_TYPE, C_TYPE}; 
TypeTag typeTag; 
}; 

Và sau đó trong constructor của lớp con:

B::B() 
: typeTag(TypeTag::B_TYPE) 
{ 
... 
} 

C::C() 
: typeTag(TypeTag::C_TYPE) 
{ 
... 
} 
+0

typeTag tốt hơn là riêng tư. Không enum nhưng biến. –

+0

@Manoj: tôi không đồng ý. typeTag được khởi tạo trong hàm tạo con, vì vậy nó không thể là thành viên riêng của lớp cơ sở. – Adesit

+0

@Adesit: typeTag phải được bảo vệ. Nhưng cơ chế này không hoàn hảo, bởi vì khi thêm hậu duệ mới, chúng ta cần thêm thành viên mới của enum. Trân trọng gửi đến Odessa :) – zabulus

0

Có một tính năng trong C++ gọi RTTI (loại runtime thông tin) cho phép bạn làm những việc như vậy.

Một khả năng khác để kiểm tra loại thời gian chạy là tạo lớp cơ sở mà từ đó tất cả các lớp của bạn bắt nguồn từ đó. Trong lớp cơ sở của bạn bao gồm một trường chứa loại của nó dưới dạng một chuỗi hoặc một số.

0

Một mẹo nhỏ có thể có hoặc không có thể làm việc với RTTI, tùy thuộc vào trình biên dịch của bạn, như sau

const type_info &a1_type_info= typeid(*a1); 
const type_info &a2_type_info= typeid(*a2); 

return &a1_type_info==&a2_type_info || a1_type_info==a2_type_info; 

Nếu trình biên dịch của bạn tạo ra type_info trường bởi giá trị, điều này sẽ không thử nghiệm đầu tiên nhưng thành công trên thứ hai kiểm tra. Nếu trình biên dịch của bạn lưu trữ các cá thể, phép thử đầu tiên sẽ thành công (nếu nó là cùng loại) và nhanh hơn nhiều vì nó chỉ là một con trỏ so sánh. Nếu trình biên dịch của bạn trả về các phiên bản khác nhau vì a1a2 đến từ các thư viện được chia sẻ khác nhau, nó vẫn hoạt động.

1

Thực tế có một câu trả lời khá đơn giản cho điều này. Nhưng nó liên quan đến việc đặt ra các câu hỏi một chút rõ ràng hơn.

(A) Nếu tôi muốn lưu trữ các đối tượng typeinfo trong một unordered_set tôi cần phải làm gì?

typeinfo hỗ trợ phương thức == và tên(). Tên có thể được sử dụng để tạo ra một băm và == cho sự bình đẳng

(B) Nếu tôi muốn lưu trữ các đối tượng typeinfo trong một order_set (std :: set), tôi cần phải làm gì?

typeinfo hỗ trợ phương thức == và before(). Với bit gói của hai phương pháp này tôi có thể thực hiện một giao diện cho một chức năng so sánh mang lại cho tôi đặt hàng yếu nghiêm ngặt.

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