5 toán tử ép kiểu trong C++

É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");
}  

Be the first to comment

Leave a Reply