Hàm khởi tạo (constructor) trong C++ | Laptrinhcanban.com

Hàm khởi tạo (constructor) trong C++

Cùm tìm hiểu về hàm khởi tạo (constructor) trong C++. Bạn sẽ biết khái niệm hàm khởi tạo (constructor) trong C++ là gì, cách khai báo cũng như cách sử dụng hàm khởi tạo constructor trong C++ sau bài học này.

Hàm khởi tạo trong c++ là gì

Hàm khởi tạo trong c++ hay còn gọi là constructor trong C++ là các hàm thành viên được tự động được thực thi khi chương trình tạo ra một đối tượng (instance) từ class, và được sử dụng với mục đích chính là khởi tạo các biến thành viên trong class đó.

Hàm khởi tạo trong c++ có 2 tính chất như sau:

  1. Tên hàm khởi tạo phải trùng với tên của class
  2. Hàm không mang kiểu dữ liệu trong nó, cũng như không sử dụng void khi khai báo nó.

Hàm khởi tạo, về bản chất cũng là một hàm thành viên trong class, tuy nhiên khác với các hàm thành viên khác thì nó chỉ có thể được gọi 1 lần duy nhất khi chúng ta tạo một instance từ class mà thôi. Sau khi đã được gọi và khởi tạo xong các biến thành viên, nó sẽ không thể được gọi thêm một lần nào nữa.

Có 2 loại hàm khởi tạo trong C++ phụ thuộc vào việc có tham số trong hàm hay không. Và nếu một hàm khởi tạo không chứa tham số trong nó thì chúng ta gọi nó là Hàm tạo mặc định (default constructor) trong C++.

Vậy vì sao chúng ta cần phải khởi tạo các biến thành viên trong class khi tạo một đối tượng (instance) từ class?

Câu trả lời rất đơn giản. Giống như khi bạn muốn rút tiền trong ví ra để sử dụng, thì bạn cần phải bỏ tiền vào ví đó trước vậy. Hành động bỏ tiền vào ví trước khi sử dụng, giống như việc khởi tạo tiền (giá trị các biến thành viên) trong ví, và khi đó người bỏ tiền (bạn hoặc người thân của bạn) vào ví giống như hàm khởi tạo trong C++ vậy.

Ví dụ chúng ta có class sau đây:

class SimpleClass
{
/*Khai báo biến thành viên*/
private:
int number;
string name;

/*Khai báo và tạo các hàm thành viên*/
public:
int getNumber() { return number; } /*Tạo hàm getNumber để lấy giá trị number*/
void setNumber(int n) { number = n; } /*Tạo hàm setNumber để đổi giá trị number*/

std::string getName() { return name; }/*Tạo hàm getName để lấy giá trị name*/
void setName(char* s) { name = s; }/*Tạo hàm setName để đổi giá trị name*/
};

Với class này, nếu chúng ta không khởi tạo giá trị cho biến thành viên (number và name) trước, thì sẽ xảy ra lỗi khi chạy chương trình như sau:

int main()
{
SimpleClass sc;

std::cout << sc.getNumber();
//Lỗi compile do giá trị các biến chưa được khởi tạo
}

Do vậy, nếu chúng ta không quản lý được việc khởi tạo giá trị của biến thành viên trong class, thì đây sẽ là nơi tiềm tàng để xảy ra các bug khi viết chương trình C++. Tất nhiên chúng ta cũng có thể tự khởi tạo giá trị của các biết thành viên trong class, nhưng nếu như thế thì lần nào sử dụng class đều cần phải viết lại khai báo.

Do đó để tiện lợi và tránh bug khi viết chương trình thì hàm khởi tạo (constructor) trong C++ đã ra đời và giúp chúng ta khởi tạo giá trị các biến thành viên khi tạo một instance từ class.

Khai báo hàm khởi tạo trong C++

Hàm khởi tạo (constructor) lần lượt được khai báo, và viết các xử lý chi tiết trong các file classname.hclassname.cpp với cú pháp như sau:

“MyClass.h”:

class MyClass {
public:
MyClass(); //Khai báo hàm khởi tạo cùng tên với class
};

“MyClass.cpp”:

#include "MyClass.h"

MyClass::MyClass()
{
//..... //Viết lệnh khởi tạo các biến thành viên trong hàm
}

Tất nhiên đối với các chương trình nhỏ thì chúng ta cũng có thể viết gộp chúng lại trong một file .cpp duy nhất như sau:

class MyClass {
public:
MyClass() //Khai báo hàm khởi tạo cùng tên với class
{
//..... // Viết lệnh khởi tạo các biến thành viên trong hàm
}
};

Giống như trên thì hàm khởi tạo không mang kiểu dữ liệu của nó, cũng như không sử dụng tới void khi khai báo. Đây là điểm khác biệt của hàm khởi tạo so với các hàm thông thường trong C++, và chúng ta cần chú ý cũng như dùng tính chất này để nhận biết một hàm khởi tạo trong class C++.

Lưu ý cách viết chia file như trên thường được sử dụng trong các dự án lớn, khi cần có sự phân chia công việc và hợp tác nhóm. Đối với các chương trình nhỏ thì chỉ cần dùng cách viết gộp thứ 2 là đủ.

Hàm khởi tạo mặc định trong C++ (Default constructor)

Chúng ta gọi một hàm khởi tạo không chứa tham số trong nó là Hàm tạo mặc định (Default constructor) trong C++.

Khai báo hàm khởi tạo mặc định trong C++

Để khai báo hàm khởi tạo mặc định trong C++, chúng ta viết toán tử bằng = giữa tên biến thành viên và giá trị của biến đó trong dấu ngoặc với cú pháp sau đây:

class MyClass {
private:
int m_a;

public:
MyClass()
{
m_a = 123;
}
};

Trong đó m_a là tên biến thành viên và 123 là giá trị dùng để khởi tạo nó.

Trong trường hợp có nhiều biến thành viên trong class, chúng ta khai báo các biến cách nhau bởi dấu chấm phẩy như sau:

class MyClass {
private:
int m_a;
int m_b;

public:
MyClass()
{
m_a = 123;
m_b = 45;
}
};

Sử dụng class chứa hàm khởi tạo mặc định trong C++

Do hàm khởi tạo mặc định không chứa tham số, nên lưu ý khi tạo một instance từ class, chúng ta sẽ không truyền đối số vào hàm và viết trực tiếp tên của instance tạo ra từ class như sau:

int main()
{
MyClass sc1;
}

Đây là điểm rất khác biệt khi chúng ta sử dụng một class mà hàm khởi tạo của nó chứa tham số.

Ví dụ, chúng ta dùng hàm khởi tạo để khởi tạo giá trị của biến thành viên number của class sau đây với giá trị bằng 0 như sau:

#include <iostream>
#include <string>
using namespace std;

class SimpleClass
{
private:
int number;
string name;

public:
//Khai báo hàm khởi tạo constructor
SimpleClass()
{
//Khởi tạo giá trị biến thành viên number
number = 0; // number(0);
}

int getNumber() { return number; } /*Tạo hàm getNumber để lấy giá trị number*/
void setNumber(int n) { number = n; } /*Tạo hàm setNumber để đổi giá trị number*/

string getName() { return name; }/*Tạo hàm getName để lấy giá trị name*/
void setName(char* s) { name = s; }/*Tạo hàm setName để đổi giá trị name*/
};

int main()
{
SimpleClass sc;
//Sau khi tạo instance sc, thì tại thời điểm này sc.number được khởi tạo bằng 0

cout << sc.getNumber(); //0
}

Lưu ý ở ví dụ trên, do biến thành viên name thuộc kiểu String, nên nó sẽ được khởi tạo với giá trị mặc định là ký tự trống. Do vậy chúng ta không cần khởi tạo nó trong hàm khởi tạo nữa. Đây là một đặc thù của hàm khởi tạo trong class String trong C++.

Hàm khởi tạo có tham số trong C++

Ngoài loại hàm khởi tạo mặc định thì giống với các hàm khác trong C++, chúng ta cũng có thể chỉ định tham số khi khai báo một hàm khởi tạo trong C++.

Như các hàm khác thì chúng ta chỉ định các biến làm tham số trong hàm khởi tạo trong C++ như sau:

class MyClass {
private:
int m_a;

public:
MyClass(int a)
{
m_a = a ; // Sử dụng giá trị biến a để khởi tạo biến thành viên m_a
}
};

Với hàm khởi tạo kiểu này, khi tạo instance thì chúng ta cần truyền giá trị từ bên ngoài vào tham số trong classs, bằng cách viết giá trị truyền vào giữa cặp dấu ngoặc () như sau:

int main()
{
MyClass sc1(123);
}

Ví dụ cụ thể:

#include <iostream>
#include <string>
using namespace std;

class SimpleClass
{
private:
int number;
string name;

public:
/*Hàm khởi tạo mặc định không chứa tham số*/
SimpleClass()
{
number = 0;
}

/*Hàm khởi tạo chứa tham số*/
SimpleClass(int n, string s)
{
number = n;
name = s;
}

int getNumber() { return number; }
void setNumber(int n) { number = n; }

string getName() { return name; }
void setName(string s) { name = s; }
};

int main()
{
/*Taọ instance với hàm khởi tạo mặc định*/
SimpleClass sc1;
//number: 0 name:
cout << "number: " << sc1.getNumber();
cout << "\nname: " << sc1.getName() << endl;

/*Taọ instance với hàm khởi tạo chứa tham số, chúng ta cần truyền giá trị từ ngoài vào class*/
SimpleClass sc2(1, "Kiyoshi");
cout << "number: " << sc2.getNumber();
cout << "\nname: " << sc2.getName() << endl;
}

Kết quả:

number: 0
name:
number: 1
name: Kiyoshi

Tổng kết

Trên đây Kiyoshi đã hướng dẫn bạn về hàm khởi tạo (constructor) trong C++ rồi. Để nắm rõ nội dung bài học hơn, bạn hãy thực hành viết lại các ví dụ của ngày hôm nay nhé.

Và hãy cùng tìm hiểu những kiến thức sâu hơn về C++ trong các bài học tiếp theo.

Hãy chia sẻ và cùng lan tỏa kiến thức lập trình Nhật Bản tại Việt Nam!

HOME>> >>

Profile
きよしです!笑

Tác giả : Kiyoshi (Chis Thanh)

Kiyoshi là một cựu du học sinh tại Nhật Bản. Sau khi tốt nghiệp đại học Toyama năm 2017, Kiyoshi hiện đang làm BrSE tại Tokyo, Nhật Bản.