Ép kiểu là gì?
Ép kiểu (Casting) là quá trình convert từ kiểu dữ liệu A sang kiểu dữ liệu B. C++ có 2 kiểu casting.
Implicit conversion: việc ép kiểu được thực hiện tự động bởi compiler.
int iVar = 10; float fVar = iVar; //fVar = 10.00
Explicit conversion: ép kiểu được thực hiện bởi lập trình viên.
int iVar = 20; float fVar = (float)iVar / 10;
Ngôn ngữ C++ support 5 toán tử ép kiểu.
– static_cast
– const_cast
– reinterpret_cast
– dynamic_cast
static_cast
static_cast <type-id> ( expression )
Convert expression thành kiểu dữ liệu type-id.
Một số lưu ý khi sử dụng static_cast
– Không có check run-time, do vậy ko đảm bảo an toàn khi sử dụng static_cast trong 1 số trường hợp.
– static_cast thường được sử dụng ép kiểu từ int –> float, float –> double,…
– Có thể sử dụng static_cast để convert pointer to base-class sang pointer to derived-class (không khuyến cáo sử dụng cách này, nên sử dụng dynamic_cast)
Ví dụ 1:
// static_cast_Operator.cpp // compile with: /LD class B {}; class D : public B {}; void f(B* pb, D* pd) { D* pd2 = static_cast<D*>(pb); // Not safe, D can have fields // and methods that are not in B. B* pb2 = static_cast<B*>(pd); // Safe conversion, D always // contains all of B. }
Trong ví dụ 1,
– Line B* pb2 = static_cast<B*>(pd); an toàn vì các thuộc tính và method của class B đều thuộc class D.
– Line D* pd2 = static_cast<D*>(pb); không an toàn vì class D có các thuộc tính và method mà class B không có. Tuy nhiên, câu lệnh này không báo lỗi khi chạy runtime vì toán tử static_cast không có check runtime (khác với toán tử dynamic_cast). Điều thực sự nguy hiểm khi sử dụng *pd2 truy cập tới thuộc tinh và method chỉ thuộc lớp D và không thuộc lớp B –> Chương trình crash do ACCESS VIOLATION.
Ví dụ 2:
// static_cast_Operator_2.cpp // compile with: /LD /GR class B { public: virtual void Test(){} }; class D : public B {}; void f(B* pb) { D* pd1 = dynamic_cast<D*>(pb); D* pd2 = static_cast<D*>(pb); }
Trong ví dụ 2,
– Nếu pb thực sự trỏ tới đối tượng class D, thì pd1 và pd2 sẽ có cùng giá trị, pd1 và pd2 sẽ có cùng giá trị nếu pd == 0 (NULL).
– Nếu pb trỏ tới đối tượng class B, thì dynamic_static sẽ trả về 0, nhưng static_cast không thể detect được vấn đề này. Do vậy, trong trường hợp sử dụng static_cast, lập trình viên phải kiểm tra nếu pb trỏ tới đối tượng class D thì mới trả về con trỏ trỏ tới class D.
Ví dụ 3:
// static_cast_Operator_3.cpp // compile with: /LD /GR typedef unsigned char BYTE; void f() { char ch; int i = 300; float f = 2.5; double dbl; ch = static_cast<char>(i); // int to char dbl = static_cast<double>(f); // float to double i = static_cast<BYTE>(ch); }
Trong ví dụ 3,
– Toán tửstatic_cast được sử dụng để ép kiểu cho các kiểu dữ basic. Từ int –> char, float –> double, char –> int.
– Câu lệnh “ch = static_cast(i); // int to char” gây ra mất dữ liệu vì kiểu char (1 byte) không đủ chứa kiểu int (4 bytes). Do vậy, chỉ ép kiểu từ kiểu dữ liệu NHỎ –> kiểu dữ liệu TO để tránh convert sai.
const_cast
const_cast < type-id > ( expression )
// expre_const_cast_Operator.cpp // compile with: /EHsc #include <iostream> using namespace std; class CCTest { public: void setNumber( int ); void printNumber() const; private: int number; }; void CCTest::setNumber( int num ) { number = num; } void CCTest::printNumber() const { cout << "\nBefore: " << number; const_cast< CCTest * >( this )->number--; cout << "\nAfter: " << number; } int main() { CCTest X; X.setNumber( 8 ); X.printNumber(); system("pause"); }
Leave a Reply
You must be logged in to post a comment.