2009-06-21 34 views
53

Tôi đã tự hỏi nếu có thể trong C++ để lấy tên của một lớp ở dạng chuỗi mà không cần phải hardcode nó vào một biến hoặc một getter. Tôi biết rằng không có thông tin nào trong số đó thực sự được sử dụng trong thời gian chạy, vì nó không có sẵn, nhưng có bất kỳ macro nào có thể được tạo để tạo chức năng này không?Lấy một tên lớp C++ theo lập trình

Chỉnh sửa: Có thể hữu ích khi lưu ý rằng tôi thực sự đang cố truy xuất tên của lớp dẫn xuất và tôi đang sử dụng Visual C++ 2008 Express Edition.

+0

vì đây là trình biên dịch phụ thuộc, bạn làm việc với trình biên dịch nào? –

+0

Tôi đang sử dụng hình ảnh C++ 2008 express, và tôi đoán sẽ hữu ích khi lưu ý rằng tôi thực sự đang cố truy xuất tên của lớp dẫn xuất – Morgan

Trả lời

84

Bạn có thể sử dụng typeid:

#include <typeinfo> 
cout << typeid(obj).name() << endl; 

Tuy nhiên, điều này không được khuyến khích từ các định dạng không được tiêu chuẩn hóa và có thể khác nhau giữa các trình biên dịch khác nhau (hoặc các phiên bản thậm chí khác nhau của trình biên dịch như nhau).

+0

Thú vị, tôi không biết về điều này. Công việc có vẻ tốt. Nó cho tôi một chút văn bản hơn tôi muốn trong phản hồi, nhưng nó có vẻ hoạt động khá tốt. Cảm ơn! – Morgan

+0

Tác phẩm này có không có phương pháp ảo trong lớp không? Tôi mặc dù RTTI không hoạt động trong trường hợp này. Tôi đoán miễn là bạn có một destructor ảo bạn sẽ không sao. – LeopardSkinPillBoxHat

+5

@LeopardSkinPillBoxHat: Có, nó sẽ hoạt động (xem §5.2.8/3 và 4). Đó là một quan niệm sai lầm phổ biến rằng 'typeid' sẽ chỉ hoạt động với các loại đa hình, có thể xuất phát từ sự giống nhau với các tính năng RTTI. - Trong thực tế, việc sử dụng 'typeid' trên các kiểu tĩnh không cần, và không sử dụng, RTTI. Toán tử được đánh giá tại thời gian biên dịch và kết quả được biên dịch (nói đúng, đó là một chi tiết triển khai nhưng đó là việc thực hiện duy nhất sane). –

35

Nếu bạn chỉ muốn kiểm tra xem nó là môn học nhất định, sau đó

typeid(obj) == typeid(CSubClass) 

sẽ luôn luôn làm việc không phụ thuộc vào hiện thực.

Nếu không, một cách thuận tiện là để tuyên bố:

virtual const char* classname() { return "CMyClass";} 

và thực hiện mỗi lớp con.

+0

Giải pháp tuyệt vời. Dễ dàng, đơn giản, hoạt động - trên mọi phiên bản :) –

+2

Dễ dàng, đơn giản, biên dịch. Sai, không may. 'typeid()' trả về một 'typeinfo *', một con trỏ. Nếu hai con trỏ 'typeinfo *' bằng nhau, chúng tham chiếu đến cùng một kiểu, nhưng nếu chúng không bằng nhau, chúng vẫn có thể tham chiếu đến cùng một kiểu. Đó là lý do tại sao có một lớp 'std :: type_index' với ngữ nghĩa thích hợp. 'std :: type_index (typeid (obj)) == std :: type_index (typeid (CSubClass))' sẽ là true ** nếu và chỉ khi ** hai kiểu là bằng nhau. – MSalters

8

Điều typeid (obj) .name() luôn cung cấp loại biến như được khai báo, không phải kiểu thực (lớp) của đối tượng. Nếu biến obj được gán cho một thể hiện của một lớp con của lớp mà obj được khai báo là, typeid không tiết lộ điều đó, thật không may.

+7

Sử dụng GCC 4.7.3, sử dụng typeid (* somePtr) .name() cung cấp cho tôi tên của các lớp cụ thể. – notlesh

+3

Tôi chạy vào cùng một vấn đề, nhưng nhận xét của stephelton @ làm tôi nhận ra tôi đã gọi nó trên một con trỏ thay vì đối tượng thực tế hoặc tham chiếu và nó đã trả về kiểu con trỏ! Chỉ cần thêm '*' mọi thứ cố định. –

+0

Xác nhận cả hai nhận xét trên cho VS. Sau 'BaseClass * ptr = new SubClass;' Tôi tìm 'typeid (ptr) .name()' tạo ra 'lớp BaseClass *', và 'typeid (* ptr) .name()' cho 'lớp SubClass'. –

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