Constructor Trong C++

Constructor Trong C++

Trong bài học hôm nay chúng ta sẽ cùng tìm hiểu về hàm xây dựng (constructor) trong C++ nhé. Vậy hàm xây dựng (constructor) trong C++ là gì? Nó được sử dụng như thế nào? Nó có khác gì so với các hàm bình thường trong C++.

I. Constructor Trong C++ Là Gì

 + Constructor Mặc Định Trong C++

Một constructor không có tham số truyền vào (hoặc có tham số mà tất cả chúng đều có giá trị mặc định) được gọi là constructor mặc định. Khi sử dụng một constructor, nếu không có giá trị khởi tạo nào do người dùng cung cấp được truyền cho constructor này, thì constructor mặc định sẽ được gọi.

Dưới đây là ví dụ về một class có một constructor mặc định:

/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

#include <iostream>
 
class Fraction
{
private:
    int m_numerator;
    int m_denominator;
 
public:
    Fraction() // default constructor
    {
         m_numerator = 0;
         m_denominator = 1;
    }
 
    int getNumerator() { return m_numerator; }
    int getDenominator() { return m_denominator; }
    double getValue() { return static_cast<double>(m_numerator) / m_denominator; }
};
 
int main()
{
    Fraction frac; // Since no arguments, calls Fraction() default constructor
    std::cout << frac.getNumerator() << "/" << frac.getDenominator() << '\n';
 
    return 0;
}

Class này được thiết kế để giữ một giá trị phân số dưới dạng tử số và mẫu số kiểu integer. Một constructor mặc định có tên là Fraction (cùng tên với class) đã được định nghĩa bên trong class này.

Bởi vì chúng ta đang khởi tạo một đối tượng thuộc kiểu Fraction mà không có đối số nào được truyền vào, nên constructor mặc định sẽ được gọi ngày sau khi bộ nhớ được cấp phát cho đối tượng này, và đối tượng của chúng ta sẽ được khởi tạo.

–>
Đoạn chương trình ví dụ ở trên sẽ in ra kết quả:

0/1
Lưu ý rằng tử số (numerator) và mẫu số (denominator) của chúng ta đã được khởi tạo bằng các giá trị mà ta đã thiết lập bên trong constructor mặc định! Nếu không có constructor mặc định, tử số và mẫu số sẽ có các giá trị rác cho đến khi chúng ta gán rõ ràng cho chúng các giá trị hợp lý, hoặc là khởi tạo chúng bằng các phương tiện khác (hãy nhớ rằng: Các biến thuộc các kiểu dữ liệu cơ bản đều không được khởi tạo theo mặc định).

+ Constructor Có Tham Số Trong C++

Một constructor mặc định trong C++ không có bất kỳ tham số nào, nhưng nếu bạn cần, một constructor có thể có các tham số. Điều này giúp bạn gán giá trị khởi tạo tới một đối tượng tại thời điểm tạo nó, như trong ví dụ sau:

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setChieuDai( double dai );
      double layChieuDai( void );
      Line(double dai);  // Day la phan khai bao constructor
 
   private:
      double chieudai;
};
 
// phan dinh nghia cac ham thanh vien, bao gom constructor
Line::Line( double dai)
{
    cout << "Doi tuong dang duoc tao, chieudai = " << dai << endl;
    chieudai = dai;
}
 
void Line::setChieuDai( double dai )
{
    chieudai = dai;
}
 
double Line::layChieuDai( void )
{
    return chieudai;
}
// ham main cua chuong trinh
int main( )
{
   Line line(10.0);
 
   // lay chieu dai da duoc khoi tao ban dau.
   cout << "Chieu dai cua line la: " << line.layChieuDai() <<endl;
   // thiet lap chieu dai mot lan nua
   line.setChieuDai(6.0); 
   cout << "Chieu dai cua line la: " << line.layChieuDai() <<endl;
 
   return 0;
}

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

Constructor Có Tham Số Trong C++
Constructor Có Tham Số Trong C++

IV. Ý Nghĩa Của Constructor Trong C++

Trong C++, hàm xây dựng (constructor) là một phương thức đặc biệt được gọi tự động tại thời điểm đối tượng được tạo. Mục đích của hàm xây dựng là để khởi tạo các thành viên dữ liệu của đối tượng.
Hàm xây đựng phải cùng tên với tên lớp và không có bất cứ kiểu gì trả về kể cả kiểu void.

Ví dụ ta có lớp học sinh có 2 thuộc tính là mã số học sinh và tên, thì hàm xây dựng có thể định nghĩa cho lớp học sinh như sau:

Ví dụ

class HocSinh {
    int mshs;
    string ten;
    public:
        HocSinh();
        HocSinh(int m) {
            mshs = m;
        }
        HocSinh(string t) {
            ten = t;
        }
        HocSinh(int m, string t) {
            mshs = m;
            ten = t;
        }
};

Từ chương trình trên ta thấy, chúng ta có thể tạo hàm xây dựng có tham số hoặc không có tham số đều được.

Trong C++ hàm xây dựng không có tham được gọi là hàm xây dựng mặc nhiên (Default constructor), hàm xây dựng có tham số được gọi là hàm xây dựng tham số (Parameterized constructor). Chúng ta sẽ cùng tìm hiểu từng loại hàm xây dựng một nhé

V. Copy Constructor Trong C++

Copy constructor là một constructor mà tạo một đối tượng bằng việc khởi tạo nó với một đối tượng của cùng lớp đó, mà đã được tạo trước đó. Copy constructor được sử dụng để:

Khởi tạo một đối tượng từ đối tượng khác với cùng kiểu.

Sao chép một đối tượng để truyền nó như là một tham số tới một hàm.

Sao chép một đối tượng để trả về nó từ một hàm.

Nếu một copy constructor không được định nghĩa trong một lớp, compiler sẽ tự nó định nghĩa một copy constructor. Nếu lớp có các biến con trỏ và có một số cấp phát bộ nhớ động, thì nó là một sự cần thiết để có một copy constructor. Form phổ biến nhất của copy constructor trong C++ là:

ten_lop (const ten_lop &obj) {
   // phan than cua constructor
}

Ở đây, obj là một tham chiếu tới một đối tượng mà đang được sử dụng để khởi tạo đối tượng khác.

#include <iostream>

using namespace std;

class Line
{
   public:
      int layChieuDai( void );
      Line( int dai );             // Day la mot constructor don gian
      Line( const Line &obj);  // Day la copy constructor
      ~Line();                     // Day la destructor

   private:
      int *contro;
};

// Phan dinh nghia cac ham thanh vien, bao gom constructor, copy constructor, destructor
Line::Line(int dai)
{
    cout << "Constructor: cap phat bo nho cho con tro contro" << endl;
    // cap phat bo nho cho con tro
    contro = new int;
    *contro = dai;
}

Line::Line(const Line &obj)
{
    cout << "Copy constructor: cap phat bo nho cho con tro contro" << endl;
    contro = new int;
   *contro = *obj.contro; // sao chep gia tri
}

Line::~Line(void)
{
    cout << "Giai phong bo nho!" << endl;
    delete contro;
}
int Line::layChieuDai( void )
{
    return *contro;
}

void hienThi(Line obj)
{
   cout << "Chieu dai cua line la: " << obj.layChieuDai() <<endl;
}

// ham main cua chuong trinh
int main( )
{
   Line line(50);

   hienThi(line);

   return 0;
}

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

Bạn theo dõi cùng ví dụ trên những với một sự thay đổi nhỏ để tạo đối tượng khác bởi sử dụng đối tượng đã tồn tại với cùng kiểu.

#include <iostream>

using namespace std;

class Line
{
   public:
      int layChieuDai( void );
      Line( int dai );             // Day la mot constructor don gian
      Line( const Line &obj);  // Day la copy constructor
      ~Line();                     // Day la destructor

   private:
      int *contro;
};

// Phan dinh nghia cac ham thanh vien, bao gom constructor, copy constructor, destructor
Line::Line(int dai)
{
    cout << "Constructor: cap phat bo nho cho con tro contro" << endl;
    // cap phat bo nho cho con tro
    contro = new int;
    *contro = dai;
}

Line::Line(const Line &obj)
{
    cout << "Copy constructor: cap phat bo nho cho con tro contro" << endl;
    contro = new int;
   *contro = *obj.contro; // sao chep gia tri
}

Line::~Line(void)
{
    cout << "Giai phong bo nho!" << endl;
    delete contro;
}
int Line::layChieuDai( void )
{
    return *contro;
}

void hienThi(Line obj)
{
   cout << "Chieu dai cua line la: " << obj.layChieuDai() <<endl;
}

// Ham main cua chuong trinh
int main( )
{
   Line line1(45);

   Line line2 = line1; // Lenh nay cung goi copy constructor

   hienThi(line1);
   hienThi(line2);

   return 0;
}

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

Copy Constructor Trong C++
Copy Constructor Trong C++

VI. Move Constructor Trong C++

Hàm getContainer() ở đây là một rvalue, vì vậy nó có thể được tham chiếu bởi một tham chiếu rvalue. Ngoài sử dụng tham chiếu rvalue, chúng ta cũng có thể nạp chồng các hàm. Lần này, chúng ta sẽ nạp chồng cho Hàm tạo của lớp Container và Hàm tạo mới này sẽ được gọi là hàm tạo di chuyển (move constructor).

Hàm tạo di chuyển lấy tham chiếu rvalue làm đối số và nạp chồng vì hàm tạo sao chép lấy tham chiếu const lvalue làm đối số. Trong hàm tạo di chuyển, chúng ta chỉ di chuyển các biến thành viên của đối tượng được truyền vào các biến thành viên của đối tượng mới, thay vì cấp phát bộ nhớ mới cho chúng.

Hãy xem hàm khởi tạo di chuyển cho lớp Container như sau,

Container(Container &amp;&amp; obj)
{
    // Just copy the pointer
    m_Data = obj.m_Data;
    // Set the passed object's member to NULL
    obj.m_Data = NULL;
    std::cout&lt;&lt;"Move Constructor"&lt;&lt;std::endl;
}

Trong hàm tạo di chuyển, chúng ta chỉ sao chép con trỏ. Bây giờ biến thành viên m_Data trỏ đến cùng một bộ nhớ trên heap. Sau đó, ta đặt m_Data của đối tượng được truyền thành NULL. Vì vậy, chúng ta đã không phân bổ bất kỳ bộ nhớ nào trên heap trong hàm tạo di chuyển mà chỉ chuyển quyền kiểm soát bộ nhớ.

Bây giờ nếu chúng ta tạo vector lớp Container và đẩy một đối tượng trả về từ getContainer() vào đó. Sau đó, một đối tượng mới sẽ được tạo từ đối tượng tạm thời này nhưng vì getContainer() là một rvalue, vì vậy hàm tạo di chuyển của đối tượng của lớp Container mới này sẽ được gọi và trong bộ nhớ đó sẽ chỉ được dịch chuyển. Vì vậy, thực tế trên heap, chúng ta sẽ chỉ tạo một mảng các số nguyên.

Tương tự như hàm tạo di chuyển (Move Constructor), chúng ta có thể có toán tử gán di chuyển (Move Assignment). Hãy xem ví dụ đầy đủ như sau,

#include &lt;iostream>
#include &lt;vector>
class Container {
    int * m_Data;
public:
    Container() {
        //Allocate an array of 20 int on heap
        m_Data = new int[20];
        std::cout &lt;&lt; "Constructor: Allocation 20 int" &lt;&lt; std::endl;
    }
    ~Container() {
        if (m_Data) {
            delete[] m_Data;
            m_Data = NULL;
        }
    }
    //Copy Constructor
    Container(const Container &amp; obj) {
        //Allocate an array of 20 int on heap
        m_Data = new int[20];
        //Copy the data from passed object
        for (int i = 0; i &lt; 20; i++)
            m_Data[i] = obj.m_Data[i];
        std::cout &lt;&lt; "Copy Constructor: Allocation 20 int" &lt;&lt; std::endl;
    }
    //Assignment Operator
    Container &amp; operator=(const Container &amp; obj) {
        if(this != &amp;obj)
        {
            //Allocate an array of 20 int on heap
            m_Data = new int[20];
            //Copy the data from passed object
            for (int i = 0; i &lt; 20; i++)
                m_Data[i] = obj.m_Data[i];
            std::cout &lt;&lt; "Assigment Operator: Allocation 20 int" &lt;&lt; std::endl;
        }
    }
    // Move Constructor
    Container(Container &amp;&amp; obj)
    {
        // Just copy the pointer
        m_Data = obj.m_Data;
        // Set the passed object's member to NULL
        obj.m_Data = NULL;
        std::cout&lt;&lt;"Move Constructor"&lt;&lt;std::endl;
    }
    // Move Assignment Operator
    Container&amp; operator=(Container &amp;&amp; obj)
    {
        if(this != &amp;obj)
        {
            // Just copy the pointer
            m_Data = obj.m_Data;
            // Set the passed object's member to NULL
            obj.m_Data = NULL;
            std::cout&lt;&lt;"Move Assignment Operator"&lt;&lt;std::endl;
        }
    }
};
// Create am object of Container and return
Container getContainer()
{
    Container obj;
    return obj;
}
int main() {
    // Create a vector of Container Type
    std::vector&lt;Container> vecOfContainers;
    //Add object returned by function into the vector
    vecOfContainers.push_back(getContainer());
    Container obj;
    obj = getContainer();
    return 0;
}

Kết quả:

Constructor: Allocation 20 int
Move Constructor
Constructor: Allocation 20 int
Constructor: Allocation 20 int
Move Assignment Operator

Trong ví dụ trên, hàm tạo di chuyển của lớp Container sẽ được gọi vì getContainer() trả về rvalue và lớp Container có hàm nạp chồng của hàm tạo chấp nhận rvalue trong tham số. Trong bộ nhớ hàm tạo di chuyển này chỉ được dịch chuyển con trỏ đến đối tượng được truyền. Tương tự, khi ta gán một đối tượng, toán tử gán di chuyển được sử dụng thay vì phép gán thông thường (dòng 71 và 72).

VII. Kế Thừa Constructor Trong C++

Khi kế thừa một hoặc nhiều lớp cha, chúng ta thường sử dụng lại phương thức khởi tạo (constructor method) của lớp cha vì cos nhiều lợi ích khác nhau như không phải viết lại cùng một đoạn code, khi sửa chỉ cần sửa 1 nơi,…

+ Sử dụng lại constructor trong C++

Để sử dụng constructor của lớp cha, chúng ta khai báo constructor của lớp con có dạng như sau:

LopCon::LopCon(type var1, type var2) : LopCha(var1, var2) {
    // code của bạn
}

Ví dụ minh họa

Giả sử chúng ta có lớp A như sau:

class A {
    protected:
        int x;
    public:
        A() {
            x = 0;
        }
 
        A(int x) {
            this->x = x;
        }
 
        void xuatA() {
            std::cout << "x = " << x << "n";
        }
};

Và lớp B kế thừa lớp A:

class B: public A {
    private:
        int y;
    public:
        B(int x, int y) : A(x) {// su dung constructor cua lop A
            this->y = y;
        }   
 
        void xuatB() {
            A::xuatA(); // su dung method cua lop A
            std::cout << "y = " << y << "n";
        }
};

Như các bạn thấy, trong ví dụ trên tôi đã sử dụng lại constructor của lớp A khi cài đặt constructor của lớp B, kết quả là tôi không phải viết lại đoạn code khởi tạo cho biến x mà chỉ phải viết đoạn code khởi tạo cho biến y

Nhìn xuống phía dưới, các bạn sẽ thấy dòng A::xuatA();, đó là cách sử dụng member của một lớp mà ở đây là lớp cha. Chúng ta cũng có thể sử dụng cách này để gọi static member của bất kì lớp nào với cú pháp như sau:

TenLop::TenMember

Toàn bộ code của chương trình minh họa:

/* Su dung member cua lop cha */
#include <iostream>
 
class A {
    protected:
        int x;
    public:
        A() {
            x = 0;
        }
 
        A(int x) {
            this->x = x;
        }
 
        void xuatA() {
            std::cout << "x = " << x << "n";
        }
};
 
class B: public A {
    private:
        int y;
    public:
        B(int x, int y) : A(x) {// su dung constructor cua lop A
            this->y = y;
        }   
 
        void xuatB() {
            A::xuatA(); // su dung method cua lop A
            std::cout << "y = " << y << "n";
        }
};
 
int main() {
    A a;
    B b(5, 10);
    a.xuatA();
    b.xuatB();
    return 0;
}

Kết quả khi chạy:

$ ./a.out 
x = 0
x = 5
y = 10

 

VIII. Các Kiểu Constructor Trong C++

+ Hàm xây dựng trong C++

Trong C++, hàm xây dựng (constructor) là một phương thức đặc biệt được gọi tự động tại thời điểm đối tượng được tạo. Mục đích của hàm xây dựng là để khởi tạo các thành viên dữ liệu của đối tượng.
Hàm xây đựng phải cùng tên với tên lớp và không có bất cứ kiểu gì trả về kể cả kiểu void.

Ví dụ ta có lớp học sinh có 2 thuộc tính là mã số học sinh và tên, thì hàm xây dựng có thể định nghĩa cho lớp học sinh như sau:

Ví dụ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class HocSinh {
    int mshs;
    string ten;
    public:
        HocSinh();
        HocSinh(int m) {
            mshs = m;
        }
        HocSinh(string t) {
            ten = t;
        }
        HocSinh(int m, string t) {
            mshs = m;
            ten = t;
        }
};

Từ chương trình trên ta thấy, chúng ta có thể tạo hàm xây dựng có tham số hoặc không có tham số đều được.

Trong C++ hàm xây dựng không có tham được gọi là hàm xây dựng mặc nhiên (Default constructor), hàm xây dựng có tham số được gọi là hàm xây dựng tham số (Parameterized constructor). Chúng ta sẽ cùng tìm hiểu từng loại hàm xây dựng một nhé

+ Hàm xây dựng mặc nhiên

Như đã nói ở trên hàm xây dựng mặc nhiên là hàm xây dựng không có tham số. Nó sẽ tự động được gọi tại thời điểm đối tượng được tạo.

Nếu lớp chúng ta không có hàm xây dựng nào thì mặc nhiên chương trình chúng ta sẽ tạo cho lớp đó một hàm xây dựng mặc nhiên.

Chúng ta cùng xem xét một ví dụ đơn giản về hàm xây dựng mặc nhiên trong C++ như sau:

Ví dụ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>  
using namespace std;  
class NhanVien {  
   public:  
        NhanVien() {    
            cout << "Ham xay dung mac nhien tu dong duoc goi." << endl;    
        }    
};  
 
int main() {  
    NhanVien e1; //khoi tao doi tuong nhan vien 1
    NhanVien e2;   //khoi tao doi tuong nhan vien 2
    return 0;  
}

Và kết quả sau khi thực thi chương trình trên như sau:

Hàm xây dựng mặc nhiên
Hàm xây dựng mặc nhiên

+ Hàm xây dựng tham số

Như đã đề cập ở trên thì một hàm xây dựng có tham số được gọi là xây dựng tham số. Mục đích của hàm xây dựng tham số là để cung cấp các giá trị khác nhau cho các đối tượng riêng biệt.

Chúng ta cùng xem xét một ví dụ đơn giản về hàm xây dựng tham số trong C++ như sau:

Và kết quả sau khi thực thi chương trình trên như sau:

Ví dụ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>  
using namespace std;  
class NhanVien { 
    int msnv;    
    string ten;
    int tuoi;
    public:  
       NhanVien(int m) {    
            msnv = m;
       }
       NhanVien(int m, string tn) {    
            msnv = m;    
            ten = tn;
            tuoi = 20;
       }
       NhanVien(int m, string tn, int t) {    
            msnv = m;    
            ten = tn;    
            tuoi = t; 
       }    
       void HienThi() {    
            cout << ten << endl;
            cout << "   Ma so nhan vien: " << msnv << endl;
            cout << "   Tuoi: " << tuoi << endl;
       }    
};  
  
int main() {  
    NhanVien n1 =  NhanVien(111231, "Nguyen Van A", 25);    
    NhanVien n2 =  NhanVien(213214, "Nguyen Van B");
    NhanVien n3 =  NhanVien(213215, "Nguyen Van C");
    n1.HienThi();    
    n2.HienThi();
    n3.HienThi();
    return 0;  
}

Và kết quả sau khi thực thi chương trình trên như sau:

Hàm xây dựng tham số
Hàm xây dựng tham số

Lưu ý:

  • Khi chúng ta không định nghĩa hàm xây dựng thì mặc nhiên chương trình sẽ tạo cho lớp đó một hàm xây dựng mặc nhiên. Chúng ta chỉ có 1 cách để khởi tạo đối tượng duy nhất đó là TenHamXayDung p1, TenHamXayDung p2, …
  • Khi chúng ta định nghĩa hàm xây dưng kể cả mặc nhiên hay tham số thì chúng ta số cách để tạo đối tương đúng bằng số hàm xây dựng mà chúng ta đã định nghĩa
  • Khi chúng ta khai báo đối tượng không khớp với bất kỳ hàm xây dựng nào mà chúng ta đã định nghĩa thì chương trình chúng ta sẽ báo lỗi.
  • Tránh khai báo nhiều hàm xây dựng vô nghĩa mà chúng ta không sử dụng để khỏi tạo đối tượng.
  • Mục đích chính của hàm xây dựng là dùng để khởi tạo giá trị cho đối tượng, tuy nhiên chúng ta có thể sử dụng hàm xây dựng theo mục đích của riêng mình.

IX. Bài Tập Constructor Trong C++

Một class contructor là một hàm thành viên đặc biệt của một lớp mà được thực thi bất cứ khi nào chúng ta tạo các đối tượng mới của lớp đó.

Một constructor sẽ có tên giống như lớp và nó không có bất kỳ kiểu trả về, kể cả kiểu void. Constructor có thể rất hữu ích để thiết lập các giá trị khởi tạo cho các biến thành viên cụ thể.

Ví dụ sau giải thích khái niệm contructor trong C++:

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setChieuDai( double dai );
      double layChieuDai( void );
      Line();  // Day la constructor
 
   private:
      double chieudai;
};
 
// phan dinh nghia cac ham thanh vien, bao gom ca constructor
Line::Line(void)
{
    cout << "Doi tuong da duoc tao!" << endl;
}
 
void Line::setChieuDai( double dai )
{
    chieudai = dai;
}
 
double Line::layChieuDai( void )
{
    return chieudai;
}
// Ham main cua chuong trinh
int main( )
{
   Line line;
 
   // thiet lap chieu dai cua line
   line.setChieuDai(6.0); 
   cout << "Chieu dai cua duong la: " << line.layChieuDai() <<endl;
 
   return 0;
}

 

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

Bài Tập Constructor Trong C++
Bài Tập Constructor Trong C++

Constructor được tham số hóa trong C++

Một constructor mặc định trong C++ không có bất kỳ tham số nào, nhưng nếu bạn cần, một constructor có thể có các tham số. Điều này giúp bạn gán giá trị khởi tạo tới một đối tượng tại thời điểm tạo nó, như trong ví dụ sau:

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setChieuDai( double dai );
      double layChieuDai( void );
      Line(double dai);  // Day la phan khai bao constructor
 
   private:
      double chieudai;
};
 
// phan dinh nghia cac ham thanh vien, bao gom constructor
Line::Line( double dai)
{
    cout << "Doi tuong dang duoc tao, chieudai = " << dai << endl;
    chieudai = dai;
}
 
void Line::setChieuDai( double dai )
{
    chieudai = dai;
}
 
double Line::layChieuDai( void )
{
    return chieudai;
}
// ham main cua chuong trinh
int main( )
{
   Line line(10.0);
 
   // lay chieu dai da duoc khoi tao ban dau.
   cout << "Chieu dai cua line la: " << line.layChieuDai() <<endl;
   // thiet lap chieu dai mot lan nua
   line.setChieuDai(6.0); 
   cout << "Chieu dai cua line la: " << line.layChieuDai() <<endl;
 
   return 0;
}

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

Bài Tập Constructor Trong C++
Bài Tập Constructor Trong C++

Sử dụng danh sách khởi tạo cho các trường khởi tạo

Trong trường hợp constructor được tham số hóa, bạn có thể sử dụng cú pháp sau để khởi tạo các trường.

Line::Line( double dai): chieudai(dai)
{
    cout << "Doi tuong dang duoc tao, chieudai = " << dai << endl;
}

Cú pháp trên là tương đương với cú pháp sau:

Line::Line( double dai)
{
    cout << "Doi tuong dang duoc tao, chieudai = " << dai << endl;
    chieudai = dai;
}

Nếu với một lớp trong C, bạn có nhiều trường X, Y, Z, … để được khởi tạo, thì bạn có thể sử dụng cú pháp tương tự và phân biệt các trường bởi dấu phảy, như sau:

C::C( double a, double b, double c): X(a), Y(b), Z(c)
{
  ....
}

Class Destructor trong C++

Một destructor là một hàm thành viên đặc biệt của một lớp mà được thực thi bất cứ khi nào một đối tượng của lớp đó ra khỏi phạm vi hoặc bất cứ khi nào biểu thức delete được áp dụng tới một con trỏ tới đối tượng của lớp đó.

Một destructor sẽ có cùng tên với lớp và được đặt trước bỏi ký hiệu ~ và nó có thể: không trả về một giá trị và không nhận bất kỳ tham số nào. Destructor có thể rất hữu ích để giải phóng resource trước khi thoát khỏi chương trình, ví dụ: đóng file, giải phóng bộ nhớ, …

Ví dụ sau giải thích khái niệm về destructor trong C++:

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setChieuDai( double dai );
      double layChieuDai( void );
      Line();   // Day la phan khai bao constructor 
      ~Line();  // Day la phan khai bao destructor
 
   private:
      double chieudai;
};
 
// phan dinh nghia ham thanh vien, bao gom constructor va destructor
Line::Line(void)
{
    cout << "Doi tuong dang duoc tao" << endl;
}
Line::~Line(void)
{
    cout << "Doi tuong dang bi xoa!" << endl;
}
 
void Line::setChieuDai( double dai )
{
    chieudai = dai;
}
 
double Line::layChieuDai( void )
{
    return chieudai;
}
// ham main cua chuong trinh
int main( )
{
   Line line;
 
   // Thiet lap chieu dai cua line
   line.setChieuDai(6.0); 
   cout << "Chieu dai cua line la: " << line.layChieuDai() <<endl;
 
   return 0;
}

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

Bài Tập Constructor Trong C++
Bài Tập Constructor Trong C++

Bài viết liên quan

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