Ép Kiểu Trong C++

Ép kiểu trong C++ là việc gán giá trị của một biến có kiểu dữ liệu này tới biến khác có kiểu dữ liệu khác. Trong bài viết ngày hôm nay, chúng ta sẽ tìm hiểu kĩ hơn về ép kiểu trong C++ qua bai viết dưới đây nhé.

I. Ép Kiểu Trong C++ Là Gì

Toán tử ép kiểu (một cast) trong C++ là 1 toán tử đặc biệt mà làm một kiểu dữ liệu này biến đổi thành kiểu dữ liệu khác. Toán tử ép kiểu là một toán tử 1 ngôi và có cùng độ ưu tiên như bất kỳ toán tử một ngôi nào khác trong C++.

Cú pháp được dùng thường xuyên của toán tử ép kiểu trong C++ là:

(kieu_du_lieu) bieu_thuc

Ở đây, kieu_du_lieu là kiểu dữ liệu bạn muốn. Dưới đây là một số toán tử ép kiểu được hỗ trợ bởi C++:

const_cast<kieu_du_lieu> (bieu_thuc): Toán tử const_cast được sử dụng để ghi đè const và/hoặc volatile. Kiểu dữ liệu bạn muốn buộc phải giống như kiểu dữ liệu nguồn ngoại trừ sự sửa đổi của những thuộc tính const hoặc volatile trong một cast. Dạng ép kiểu này thao tác thuộc tính const của đối tượng đã truyền: hoặc được thiết lập hoặc gỡ bỏ.

dynamic_cast<kieu_du_lieu> (bieu_thuc): Toán tử dynamic_cast trong C++ thực hiện một ép kiểu tại runtime mà thẩm tra tính hợp lệ của cast. Nếu cast không thể được tạo ra, cast này thất bại và biểu thức ước lượng là null. Một toán tử dynamic_cast thực hiện các cast trên các kiểu đa hình và có thể ép một con trỏ A* thành một con trỏ B* chỉ khi đối tượng đang được trỏ tới thực sự là một đối tượng B.

reinterpret_cast<kieu_du_lieu> (bieu_thuc): Toán tử reinterpret_cast trong C++ thay đổi 1 con trỏ tới bất kỳ kiểu con trỏ khác. Nó cũng cho phép ép kiểu từ con trỏ tới một kiểu integer và ngược lại.

static_cast<kieu_du_lieu> (bieu_thuc): Toán tử static_cast trong C++ thực hiện một cast không có tính đa hình. Ví dụ, nó có thể được dùng để ép kiểu một con trỏ lớp cơ sở thành một con trỏ lớp kế thừa.

Tất cả toán tử ép kiểu trên sẽ được sử dụng trong lúc làm việc với lớp và đối tượng. Bây giờ, bạn thử ví dụ sau để hiểu toán tử ép kiểu đơn giản trong C++. Copy và paste chương trình C++ sau trong tệp test.cpp, sau đó biên dịch và chạy chương trình:

#include <iostream>
using namespace std;
 
main()
{
   double a = 15.65653;
   float b = 9.02;
   int c ;
 
   c = (int) a;
   cout << "Dong 1: Gia tri cua (int)a la: " << c << endl ;
   
   c = (int) b;
   cout << "Dong 1: Gia tri cua (int)b la: " << c << endl ;
   
   return 0;
}

Chạy chương trình C++ trên sẽ cho kết quả như hình sau:

Ép Kiểu Trong C++ Là Gì
Ép Kiểu Trong C++ Là Gì

II. Cách Ép Kiểu Dữ Liệu Trong C++


III. Ép Kiểu Class Trong C++

É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

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");
}
Ép Kiểu Class Trong C++
Ép Kiểu Class Trong C++

IV. Ép Kiểu Tường Minh Trong C++

Ép kiểu tường minh (Explicit type conversion) là quá trình chuyển đổi kiểu dữ liệu một cách tường minh (rõ ràng) bởi lập trình viên, sử dụng toán tử ép kiểu (casting operator) để thực hiện việc chuyển đổi.

Trong C++, có 5 cách ép kiểu tường minh:

  • C-style casts
  • Static casts
  • Const casts
  • Dynamic casts
  • Reinterpret casts

Phạm vi bài học này sẽ nói về C-style casts và Static casts, 2 cách phổ biến nhất trong C++.

Dynamic casts, Const casts và Reinterpret casts cần những kiến thức chuyên sâu hơn, nên sẽ được bỏ qua trong bài học này.

C-style casts

Trong ngôn ngữ C chuẩn, ép kiểu được thực hiện thông qua toán tử (), và tên kiểu dữ liệu cần chuyển được đặt bên trong.

Ví dụ:

#include <iostream>
using namespace std;

int main()
{
   int n1 = 3;
   int n2 = 2;
   double d = (double)n1 / n2;

   cout << d << endl;

   return 0;
}

Trong chương trình trên, trình biên dịch (compiler) chuyển đổi biến n1 từ kiểu int sang kiểu double thông qua ép kiểu tường minh C-style. Sau đó biểu thức có 2 toán hạng có kiểu double và kiểu int, nên toán hạng kiểu int sẽ được chuyển đổi ngầm định sang kiểu double. Vì vậy, kết quả của biểu thức là phép chia giữa 2 số chấm động kiểu double.

Ngôn ngữ C++ cho phép thực hiện ép kiểu tường minh C-style với cú pháp như một lời gọi hàm:

int n1 = 3;
int n2 = 2;
double d = double(n1) / n2;

Ép kiểu tường minh C-style không được trình biên dịch (compiler) kiểm tra tại thời điểm biên dịch (compile time), nên trình biên dịch sẽ không đưa ra những cảnh báo trong những trường hợp chuyển đổi không đúng

Chú ý: Tránh sử dụng ép kiểu tường minh C-style.

static_cast

Ngôn ngữ C++ có 1 toán tử ép kiểu gọi là static_cast. Bạn đã biết đến nó trong bài KIỂU KÝ TỰ TRONG C++ (Character):

#include <iostream>
#include <iomanip>	// for std::setprecision()
using namespace std;

int main()
{
   int n{ 75 };
   cout << static_cast<char>(n) << endl; // in ký tự với mã ASCII 75

   char ch{ 'K' };
   cout << static_cast<int>(ch) << endl; // in mã ASCII của ký tự 'K'
   return 0;
}

Chương trình trên sử dụng toán tử ép kiểu static cast trong C++ để in một ký tự từ một số nguyên và ngược lại.

Sử dụng static cast trong biểu thức:

Ví dụ:

#include <iostream>
using namespace std;

int main()
{
   int n1 = 3;
   int n2 = 2;
   double d = static_cast<double>(n1) / n2;

   cout << d << endl;

   return 0;
}

Ưu điểm của toán tử static_cast là nó yêu cầu compiler kiểm tra kiểu dữ liệu tại thời điểm biên dịch chương trình, hạn chế được những lỗi ngoài ý muốn.

Chú ý: Nên sử dụng toán tử static_cast thay vì ép kiểu C-style.

 Ép Kiểu Tường Minh Trong C++
Ép Kiểu Tường Minh Trong C++

V. Ép Kiểu Con Trỏ Trong C++

 

VI. Ép Kiểu Float Trong C

Chắc hẳn khi mới bắt đầu tập tành với C/C++ ai cũng gặp trường hợp phải ép kiểu int sang float và ngược lại. Vậy bài viết này mình sẽ hướng dẫn các bạn cách ép kiểu nguyên sang kiểu thực trong C/C++.

Ép từ kiểu nguyên sang kiểu thực

Ép kiểu int sang float

Có nhiều trường hợp chúng ta phải ép kiểu từ int sang float như ví dụ dưới đây

Bài toán: Nhập vào hai số nguyên dương a và b. Hãy xuất ra kết quả a/b.

#include<iostream>
 
using namespace std;
 
int main()
{
    int a, b;
    float kq;
    cout << "Nhap a: "; cin >> a;
    cout << "Nhap b: "; cin >> b;
    if (!b) {// Hoặc if(b==0)
        cout << "Mau phai khac 0 !";
        return 0;
    }
    kq = a / b;
    cout << "Ket qua la: " << kq << endl;
    return 0;
}
Nhap a: 2
Nhap b: 3
Ket qua la: 0

Trong trường hợp trên ta bắt buộc phải ép kiểu int sang float. Cú pháp ép kiểu như sau:

 
kq = (float)a / (float)b;
kq = float(a) / float(b);

Ở trên có hai cách ép kiểu nhưng mình khuyên các bạn nên dùng cách dưới, nhìn dễ hiểu hơn.

Cùng xem lại đoạn code ở trên nhé

 
#include<iostream>
 
using namespace std;
 
int main()
{
    int a, b;
    float kq;
    cout << "Nhap a: "; cin >> a;
    cout << "Nhap b: "; cin >> b;
    if (!b) {// Hoặc if(b==0)
        cout << "Mau phai khac 0 !";
        return 0;
    }
    //kq = (float)a / (float)b;
    kq = float(a) / float(b);
    cout << "Ket qua la: " << kq << endl;
    return 0;
}
Nhap a: 2
Nhap b: 3
Ket qua la: 0.666667

Ép kiểu int sang double

Cách làm cũng tương tự như trên mà thôi.

Ép từ kiểu thực sang kiểu nguyên

Ép kiểu float sang int

Ta có thể ép kiểu dữ liệu như sau:

 
#include<iostream>
 
using namespace std;
 
int main()
{
    float a = 3.5f;
    int b = int(a);
    cout << "Sau khi ep kieu: " << b << endl;
    return 0;
}
Sau khi ep kieu: 3

Lưu ý: Khi ép kiểu từ int sang float thì chỉ nhận được các chữ số trước dấu phẩy mà thôi. Chứ không làm tròn lên nhé.

Ví dụ: int a = float(8.9) thì a sẽ nhận giá trị 8 mà thôi.

Ép kiểu double sang int

Tương tự như ép kểu float sang int.

Ép Kiểu Float Trong C
Ép Kiểu Float Trong C

VII. Ép Kiểu Int Sang String Trong C++

Hướng dẫn cách chuyển int sang string trong C++. Bạn sẽ học được cách sử dụng hàm to_string() trong C++ sau bài học này.

Chúng ta có 2 phương pháp để chuyển int sang string trong C++ như sau:

  • Sử dụng hàm template (trước C++11)
  • Sử dụng hàm to_string (từ C++11)

Chuyển float và int sang string trong C++ bằng hàm template

Phương pháp đầu tiên cũng để chuyển int sang string trong C++ đó chính là sử dụng hàm template sau đây:

#include <sstream>
template <typename T> std::string tostr(const T& t)
{
    std::ostringstream os; os<<t; return os.str();
}

Hàm template trên có tác dụng chuyển đổi kiểu số bao gồm cả int lẫn float sang kiểu string. Sau khi đã khai báo template này, chúng ta có thể sử dụng nó nhiều lần trong chương trình.

Ví dụ cụ thể, chúng ta có thể chuyển float và int sang string như chương trình sau. Lưu ý chúng ta sử dụng tới hàm typeid.name() để kiểm tra kiểu của dữ liệu trước và sau lúc đổi thay bằng hàm template.

#include <iostream>
#include <sstream>  
#include <typeinfo>

using namespace std;
 
template <typename T> string tostr(const T& t)
{
    ostringstream os; os<<t; return os.str();
}

 
int main() {
    int a = 123;
    float b = 3.45;

    cout << "Kieu cua a: "<< typeid(a).name() <<endl;
    cout << "Kieu cua b: "<<typeid(b).name() <<endl;
    
    //Kiểu sau khi thay đổi
    cout << "Kieu thay doi cua a: "<< typeid(tostr(123)).name() <<endl;
    cout << "Kieu thay doi cua b: "<<typeid(tostr(3.1415)).name() <<endl;
    return 0;
}

Kết quả, hai biến a và b với kiểu int và float đã được chuyển sang kiểu string bằng hàm tostr như sau:

Kieu cua a: i
Kieu cua b: f
Kieu thay doi cua a: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Kieu thay doi cua b: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

Chuyển int sang string trong C++ bằng hàm to_string

Để dùng hàm template ở trên, chúng ta đều cần khai báo template ở đầu mỗi chương trình, và chuyện này thật là rườm rà phải không nào?

Đó là lý do mà từ phiên bản C++11 trở đi, song hành cùng với hàm template ở trên thì các nhà phát triển C++ đã thêm vào 1 hàm mới có chức năng tương tự nhưng lại có thể sử dụng dễ dàng hơn, đó chính là hàm to_string.

Hàm to_string là 1 hàm được thêm vào từ phiên bản C++11, có tác dụng chuyển số sang string trong C++. Hàm to_string có thể chuyển tất cả các định dạng kiểu số như int, float, double sang string trong C++ với cú pháp đơn giản và ngắn gọn.

Chúng ta sử dụng hàm to_string() trong C++ với cú pháp sau đây:

to_string(num);

Trong đó num là số cần chuyển sang kiểu chuỗi string, và num có thể ở bất kiểu số nào, ví dụ như int, float, double hay short chẳng hạn.

Ví dụ cụ thể, chúng ta có thể chuyển int sang string trong C++ bằng hàm to_string và kiểm tra kiểu trước và sau khi chuyển đổi bằng hàm typeid.name() như sau:

#include <iostream>
#include <typeinfo>

using namespace std;

int main() {
    int a = 123;
    float b = 3.45;

    cout << "Kieu cua a: "<< typeid(a).name() <<endl;
    cout << "Kieu cua b: "<<typeid(b).name() <<endl;
    
    //Kiểu sau khi thay đổi
    cout << "Kieu thay doi cua a: "<< typeid(to_string(123)).name() <<endl;
    cout << "Kieu thay doi cua b: "<<typeid(to_string(3.1415)).name() <<endl;
    return 0;
}

Kết quả, hai biến a và b với kiểu int và float đã được chuyển sang kiểu string bằng hàm to_string như sau:

Kieu cua a: i
Kieu cua b: f
Kieu thay doi cua a: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Kieu thay doi cua b: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Ép Kiểu Int Sang String Trong C++
Ép Kiểu Int Sang String Trong C++

VIII. Ép Kiểu String Sang Char Trong C+

 

IX. Ép Kiểu Int Sang Char Trong C++

X. Phân Loại Ép Kiểu Trong C++

Phân loại ép kiểu trong C++

Trong C++, có hai loại ép kiểu dữ liệu:

  1. Nới rộng (widening): Là quá trình làm tròn số từ kiểu dữ liệu có kích thước nhỏ hơn sang kiểu có kích thước lớn hơn. Kiểu biến đổi này không làm mất thông tin.
  2. Thu hẹp (narrowwing): Là quá trình làm tròn số từ kiểu dữ liệu có kích thước lớn hơn sang kiểu có kích thước nhỏ hơn. Kiểu biến đổi này có thể làm mất thông tin

1. Nới rộng (widening)

Phân Loại Ép Kiểu Trong C++
Phân Loại Ép Kiểu Trong C++

Nới rộng (widening): Là quá trình làm tròn số từ kiểu dữ liệu có kích thước nhỏ hơn sang kiểu có kích thước lớn hơn. Kiểu biến đổi này không làm mất thông tin. Ví dụ chuyển từ int sang float. Chuyển kiểu loại này có thế được thực hiện ngầm định bởi trình biên dịch.

Ví dụ:

#include <iostream>
 
using namespace std;
  
int main() {
    int i = 100;
    long l = i;    // khong yeu cau chi dinh ep kieu
    float f = l;   // khong yeu cau chi dinh ep kieu
    cout << "Gia tri Int: " << i << endl;
    cout << "Gia tri Long: " << l << endl;
    cout << "Gia tri Float: " << f << endl;
    return 0;
}

Kết quả:

Giá trị Int: 100
Giá trị Long: 100
Giá trị Float:  100

2.Thu hẹp (narrowwing)

Phân Loại Ép Kiểu Trong C++
Phân Loại Ép Kiểu Trong C++

Thu hẹp (narrowwing): Là quá trình làm tròn số từ kiểu dữ liệu có kích thước lớn hơn sang kiểu có kích thước nhỏ hơn. Kiểu biến đổi này có thể làm mất thông tin như ví dụ ở trên. Chuyển kiểu loại này không thể thực hiện ngầm định bởi trình biên dịch, người dùng phải thực hiện chuyển kiểu tường minh.

Ví dụ:

#include <iostream>
 
using namespace std;
  
int main() {
    double d = 100.04;
    long l = (long) d; // yeu cau chi dinh kieu du lieu (long)
    int i = (int) l; // yeu cau chi dinh kieu du lieu (int)
    cout << "Gia tri Double: " << d << endl;
    cout << "Gia tri Long: " << l << endl;
    cout << "Gia tri Int: " << i << endl;
    return 0;
}

Kết quả:

Giá trị Double: 100.04
Giá trị Long: 100
Giá trị Int:  100

Đánh Giá Chất Lượng Bài Viết

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Leave a Reply

Your email address will not be published. Required fields are marked *

Hotline: 0984.876.750
Chat Facebook
Gọi điện ngay