Trong C ++, làm cách nào để tìm kiểu của một biến?
Trong C ++, làm cách nào để tìm kiểu của một biến?
Câu trả lời:
Bạn có thể sử dụng toán tử typeid :
#include <typeinfo>
...
cout << typeid(variable).name() << endl;
i
có nghĩa là số nguyên trên trình biên dịch của bạn. Các tên được trả về không được chỉ định bởi tiêu chuẩn.
typeid
rất viết tắt, dành riêng cho trình biên dịch và không dành cho con người. Bạn có thể "gỡ rối" chúng (đó là thuật ngữ thực tế!), Bằng mã với một cái gì đó như gcc.gnu.org/onlineocs/libstdc++/manual/ext_demangling.html , với các tiện ích dòng lệnh như c++filt
hoặc với bất kỳ trình gỡ rối trực tuyến nào khác nhau chẳng hạn như demangler.com .
Nếu bạn có một biến
int k;
Bạn có thể lấy loại của nó bằng cách sử dụng
cout << typeid(k).name() << endl;
Xem chủ đề sau trên SO: Câu hỏi tương tự
Sự khác biệt chính giữa C ++ và Javascript là C ++ là một ngôn ngữ kiểu tĩnh, javascript wile là động.
Trong các ngôn ngữ định kiểu động, một biến có thể chứa bất cứ thứ gì và kiểu của nó được cung cấp bởi giá trị mà nó nắm giữ, theo từng thời điểm. Trong các ngôn ngữ định kiểu tĩnh, kiểu của một biến được khai báo và không thể thay đổi.
Có thể có công văn động và thành phần đối tượng và kiểu con (chức năng kế thừa và ảo) cũng như kiểu điều khiển tĩnh và siêu kiểu (thông qua mẫu CRTP), nhưng trong mọi trường hợp, trình biên dịch phải biết kiểu của biến.
Nếu bạn không biết nó là gì hoặc có thể là gì, thì đó là vì bạn đã thiết kế thứ gì đó như ngôn ngữ có hệ thống kiểu động.
Nếu đúng như vậy, tốt hơn hết bạn nên nghĩ lại thiết kế của mình, vì nó đang đi vào một vùng đất không hợp với ngôn ngữ bạn đang sử dụng (hầu hết giống như đi trên đường cao tốc với một con sâu bướm hoặc trong nước với một chiếc ô tô)
Thông thường, muốn tìm kiểu của một biến trong C ++ là một câu hỏi sai. Nó có xu hướng là thứ mà bạn mang theo từ các ngôn ngữ thủ tục như C hoặc Pascal chẳng hạn.
Nếu bạn muốn viết mã các hành vi khác nhau tùy thuộc vào loại, hãy cố gắng tìm hiểu về ví dụ: nạp chồng hàm và kế thừa đối tượng . Điều này sẽ không có ý nghĩa ngay lập tức vào ngày đầu tiên sử dụng C ++ của bạn, nhưng hãy tiếp tục.
Tôi tin rằng tôi có một trường hợp sử dụng hợp lệ cho việc sử dụng typeid (), giống như cách nó hợp lệ để sử dụng sizeof (). Đối với một hàm mẫu, tôi cần viết hoa đặc biệt cho mã dựa trên biến mẫu, để tôi cung cấp chức năng và tính linh hoạt tối đa.
Nó nhỏ gọn và dễ bảo trì hơn nhiều so với việc sử dụng tính đa hình, để tạo một phiên bản của hàm cho mỗi kiểu được hỗ trợ. Ngay cả trong trường hợp đó, tôi có thể sử dụng thủ thuật này để viết phần thân của hàm chỉ một lần:
Lưu ý rằng vì mã sử dụng các mẫu, câu lệnh switch bên dưới sẽ giải quyết tĩnh thành chỉ một khối mã, tối ưu hóa loại bỏ tất cả các trường hợp sai, AFAIK.
Hãy xem xét ví dụ này, nơi chúng ta có thể cần xử lý chuyển đổi nếu T là một loại so với một loại khác. Tôi sử dụng nó cho chuyên môn hóa lớp để truy cập phần cứng trong đó phần cứng sẽ sử dụng loại myClassA hoặc myClassB. Khi không khớp, tôi cần dành thời gian chuyển đổi dữ liệu.
switch ((typeid(T)) {
case typeid(myClassA):
// handle that case
break;
case typeid(myClassB):
// handle that case
break;
case typeid(uint32_t):
// handle that case
break;
default:
// handle that case
}
typeid
đơn giản không thể là một kiểm tra tĩnh, thời gian biên dịch - theo định nghĩa - vì vậy điều này không tạo điều kiện cho bất kỳ tối ưu hóa nào. For a template function, I need to special case the code based on the template variable
Đúng vậy, điều bạn thực sự muốn là tính đa hình tĩnh thông qua thành ngữ CRTP. Đây chính xác là những gì đạt được.
Tôi không chắc liệu câu trả lời của tôi có hữu ích hay không.
Câu trả lời ngắn gọn là, bạn không thực sự cần / muốn biết loại biến để sử dụng nó.
Nếu bạn cần cung cấp một kiểu cho một biến tĩnh, thì bạn có thể chỉ cần sử dụng auto.
Trong trường hợp phức tạp hơn khi bạn muốn sử dụng "auto" trong một lớp hoặc cấu trúc, tôi khuyên bạn nên sử dụng mẫu với kiểu khai báo.
Ví dụ: giả sử bạn đang sử dụng thư viện của người khác và nó có một biến gọi là "known_var" và bạn muốn đặt nó trong một vectơ hoặc cấu trúc, bạn hoàn toàn có thể làm điều này:
template <typename T>
struct my_struct {
int some_field;
T my_data;
};
vector<decltype(unknown_var)> complex_vector;
vector<my_struct<decltype(unknown_var)> > simple_vector
Hi vọng điêu nay co ich.
CHỈNH SỬA: Để có biện pháp tốt, đây là trường hợp phức tạp nhất mà tôi có thể nghĩ đến: có một biến toàn cục không xác định. Trong trường hợp này, bạn sẽ cần c ++ 14 và biến mẫu.
Một cái gì đó như thế này:
template<typename T> vector<T> global_var;
void random_func (auto unknown_var) {
global_var<decltype(unknown_var)>.push_back(unknown_var);
}
Nó vẫn còn một chút tẻ nhạt nhưng nó gần như bạn có thể tiếp cận với các ngôn ngữ không đánh máy. Chỉ cần đảm bảo rằng bất cứ khi nào bạn tham chiếu đến biến mẫu, hãy luôn đặt đặc tả mẫu ở đó.
Nếu bạn cần so sánh giữa một lớp và một kiểu đã biết, ví dụ:
class Example{};
...
Example eg = Example();
Bạn có thể sử dụng dòng so sánh này:
bool isType = string( typeid(eg).name() ).find("Example") != string::npos;
kiểm tra typeid
tên chứa kiểu chuỗi (tên typeid có dữ liệu bị xáo trộn khác, vì vậy tốt nhất bạn nên làm s1.find(s2)
thay vì ==
).
Bạn chắc chắn có thể sử dụng typeid(x).name()
x là tên biến. Nó thực sự trả về một con trỏ const char cho kiểu dữ liệu. Bây giờ, hãy xem đoạn mã sau.
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n = 36;
char c = 'A';
double d = 1.2;
if(*(typeid(n).name()) == 'i'){
cout << "I am an Integer variable" << endl;
}
if(*((char *) typeid(d).name()) == 'd'){
cout << "I am a Double variable" << endl;
}
if(*((char *) typeid(c).name()) == 'c'){
cout << "I am a Char variable" << endl;
}
return 0;
}
Lưu ý cách đầu tiên và thứ hai cả hai nếu hoạt động.
std::cout << "I'm a variable of type " << typeid(n).name()
. (được đổi tên để ngăn chặn a / an tạo tác, nhưng điều đó có thể được khắc phục bằng một séc khác). Ngay cả khi đó, nếu bạn thực sự muốn so sánh, thì tốt hơn hết là bạn nên làmtypeid(n) == typeid(int)