2009-12-31 24 views
5

Nếu tôi hiểu chính xác, typeid có thể xác định loại thực tế trong đa hình, trong khi typeof không thể. Có phải nó cũng đúng là lợi nhuận của họ được sử dụng cho các mục đích khác nhau: sự trở lại của typeof được sử dụng như là từ khóa loại có thể xác định biến, nhưng sự trở lại của typeid có thể không?Nhận loại biến

Có cách nào để cả hai có được loại thực tế cho đa hình và sử dụng từ khóa trả về làm loại để xác định một biến khác? Tôi hy vọng có được loại lớp dẫn xuất từ ​​một con trỏ trỏ đến lớp cơ sở và định nghĩa một biến hoặc một con trỏ tới lớp dẫn xuất. Một cái gì đó như:

baseclass *p = new derivedclass 
typexxx(*p) *pp = dynamic_cast<typexxx(*p) *> (p); 
// would like to convert the pointer from pointing to a base class 
// to its derived class 

Cảm ơn bạn rất nhiều!

+6

Bạn có thể đưa ra ví dụ về TẠI SAO bạn muốn thực hiện việc này không? Điểm chính của một hệ thống phân cấp thừa kế là bạn thường không cần phải biết loại thực tế. –

+0

Chỉ muốn tham khảo một số thành viên được xác định trong lớp dẫn xuất chứ không phải trong lớp cơ sở. Tôi không chắc là nên thêm các hàm thành viên vào lớp cơ sở có cùng tên với lớp cơ sở và khai báo chúng là ảo không, vì các hàm thành viên đó quá cụ thể với lớp dẫn xuất cụ thể đó và không bắt buộc trong lớp khác các lớp dẫn xuất, và hàm cơ sở sẽ lớn hơn nếu tôi thêm chúng vào nó. – Tim

+1

OK, bạn có thể làm những gì bạn muốn với dynamic_cast, nhưng bạn sẽ cần phải sử dụng một if-ladder để tạo ra các con trỏ kiểu có nguồn gốc. –

Trả lời

7

c++0x sẽ có decltype mà có thể được sử dụng như thế này:

int someInt; 
decltype(someInt) otherIntegerVariable = 5; 

nhưng đối với đồng bằng cũ C++, không may, không có.

Tôi giả sử rằng decltype sẽ không thực sự giúp ích nhiều cho dù bạn muốn loại đa hình, không phải là loại được khai báo. Cách tiến thẳng nhất để làm những gì bạn muốn là cố gắng truyền động tới một loại cụ thể và kiểm tra NULL.

struct A { 
    virtual ~A() {} 
}; 
struct B : public A {}; 
struct C : public A {}; 

int main() { 
    A* x = new C; 
    if(B* b_ptr = dynamic_cast<B*>(x)) { 
     // it's a B 
    } else if(C* c_ptr = dynamic_cast<C*>(x)) { 
     // it's a C 
    } 
} 
+0

Cảm ơn Evan! Nhưng đôi khi tôi cần phải xác định loại lúc chạy như thông qua đối số dòng lệnh. Xem bài đăng của tôi ở đây http://stackoverflow.com/questions/1984492/runtime-determine-type-for-c, bạn sẽ hiểu. – Tim

+0

'if (B * b_ptr = dynamic_cast (x))' và không cần cho các biến số công đoàn hoặc sai phạm vi. Thêm vào đó bạn có thể viết tự nhiên 'else if' thay vì' else {... if ...} ' –

+0

@Roger: bạn học một cái gì đó mới mỗi ngày, tôi không biết rằng bạn có thể khai báo biến bên trong câu lệnh if. và dẫn đến phạm vi thích hợp. Tôi sẽ cập nhật câu trả lời của mình. –

3

Giả sử một hệ thống phân cấp Một < - B < - C

A * p = new AorBorC; // create new object of some sort 

if (dynamic_cast <C*>(p)) { 
    C * c = dynamic_cast <C*>(p); 
    c->CFunc(); 
} 
else if (dynamic_cast <B*>(p)) { 
    B * b = dynamic_cast <B*>(p); 
    b->BFunc(); 
} 
else if (dynamic_cast <A*>(p)) { 
    A * a = dynamic_cast <A*>(p); 
    a->AFunc(); 
} 

đâu AFunc, BFunc, CFunc là đặc trưng cho lớp học của mình, và không phải là ảo. Rõ ràng, điều này có thể được tối ưu hóa một chút.

+0

'if (C * c = dynamic_cast (p)) {/ * sử dụng c * /}' Không cần truyền hai lần. –

+1

Khá - Tôi đã cố gắng để làm cho mọi thứ rõ ràng hơn bằng cách dài dòng. –