Chủ Nhật, 31 tháng 3, 2019

[Học C++] Bài7- Hàm tạo(Constructor),Hàm hủy (Destructor) trong C++

Hàm tạo là 1 hàm đặc biệt,thực hiện khởi tạo cho mỗi đối tượng.Compiler sẽ gọi hàm tạo bất cứ
khi nào 1 đối tượng được tạo...Hàm tạo khởi tạo giá trị cho đối tượng sau khi lưu trữ và cấp phát cho đối tượng.
Trong khi đó,hàm hủy được sử dụng để giải phóng tài nguyên của đối tượng đã được tạo trước đó.

1. Constructor - Hàm tạo
Có 3 loại hàm tạo
- Default Constructor
- Parametrized Constructor (Hàm tạo tham số)
- Copy COnstructor
Cú pháp : [Tên class](các tham số nếu có) {}
class A
{
    public:
    int i;
    A(); // constructor declared
};
// constructor definition
A::A()  
{
    i = 1;
}

1.1 Hàm tạo mặc định
Là hàm tạo không có tham số...
Nếu trong class không có hàm tạo nào..Compiler sẽ gọi ra 1 hàm tạo mặc định.
Còn khi bạn khai báo 1 hàm tạo trong class rồi thì Compiler sẽ không tự cung cấp hàm tạo mặc định.
class Cube
{
    public:
    int side;
    Cube()
    {
        side = 10;
    }
};
int main()
{
    Cube c;
    cout << c.side;
}


1.2 Hàm tạo tham số
class Cube
{
    public:
    int side;
    Cube(int x)
    {
        side=x;
    }
};
int main()
{
    Cube c1(10);
    Cube c2(20);
    Cube c3(30);
    cout << c1.side;
    cout << c2.side;
    cout << c3.side;
}


1.3. Constructor Overloading
Giống như hàm bình thường,.. Hàm tạo cũng có thể bị overloading..
Khi chúng ta có cả default và parametrized constructors được định nghĩa trong class thì ta sẽ có Overloading COnstructor.
Ví dụ:

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class COGE{
public:
 int id;
 string name;
 // first constructor
 COGE(int x) {
  id = x;
  name = "None";
 }
 // second constructor
 COGE(int x,string str){
  id = x;
  name = str;
 }
};
int _tmain(int argc, _TCHAR* argv[])
{
 COGE nhanvien1(1);
 COGE nhanvien2(2,"Neb");
 //COGE nhanvien3;  //Error vì không có hàm tạo nào không có tham số
 system("pause");
 return 0;
}


2  Hàm tạo copy
Bản chất là copy các đối tượng đã được khởi tạo từ 1 hàm tạo có sẵn..
Cú pháp
Classname(const classname & objectname)
{
//
}

Ví dụ:
#include<iostream>
using namespace std;
class Samplecopyconstructor
{
    private:
    int x, y;   //data members
   
    public:
    Samplecopyconstructor(int x1, int y1)
    {
        x = x1;
        y = y1;
    }
   
    /* Copy constructor */
    Samplecopyconstructor (const Samplecopyconstructor &sam)
    {
        x = sam.x;
        y = sam.y;
    }
   
    void display()
    {
        cout<<x<<" "<<y<<endl;
    }
};
/* main function */
int main()
{
    Samplecopyconstructor obj1(10, 15);     // Normal constructor
    Samplecopyconstructor obj2 = obj1;      // Copy constructor
    cout<<"Normal constructor : ";
    obj1.display();
    cout<<"Copy constructor : ";
    obj2.display();
    return 0;
}
OUTPUT
Normal constructor :10 15
Copy constructor : 10 15


Vi du 2:
#include <iostream>
using namespace std;
class COGE {
public:
 int x,y;
 COGE(int a,int b) {
  x = a;
  y = b;
 }
 // ham tao copy
 COGE(const COGE &Neb) {
  x = Neb.x;
  y = Neb.y;
 }
 ~COGE() {}
};
int _tmain(int argc, _TCHAR* argv[])
{
 COGE object1(1,2);
 cout<<object1.x; //in ra 1
 //
 COGE object2(object1);
 cout<<object2.x; //in ra 1
 //
 object1.x = 5;
 cout<<object1.x; //in ra 5
 cout<<object2.x; //in ra 1
 system("pause");
 return 0;
}

Nhận xét: Khi thay đổi giá trị của đối tượng này thì không ảnh hưởng đến đối tượng kia.
Vậy, làm sao để khi thay đổi 1 đối tượng thì các đối tượng khác thay đổi theo? Sử dụng phương pháp sau… Ahihi

 2.1 Shallow Copy Constructor
Các đối tượng tạo ra sẽ trỏ vào 1 cùng 1 vùng nhớ...
Do đó khi 1 đối tượng thay đổi,các đối tượng khác cũng thay đổi theo.




Ví dụ
#include<iostream>
#include<cstring>
using namespace std;
class CopyConstructor
{
    char *s_copy;
    public:
    CopyConstructor(const char *str)
    {
        s_copy = new char[16]; //Dynamic memory allocation
        strcpy(s_copy, str);
    }
    /* concatenate method */
    void concatenate(const char *str)
    {
        strcat(s_copy, str); //Concatenating 2 strings
    }
    /* copy constructor */
    ~CopyConstructor ()
    {
        delete [] s_copy;
    }
    void display()
    {
        cout<<s_copy<<endl;
    }
};
/* main function */
int main()
{
    CopyConstructor c1("Copy");
    CopyConstructor c2 = c1; //Copy constructor
    c1.display();
    c2.display();
    c1.concatenate("Constructor");    //c1 goi concatenate()
    c1.display();
    c2.display();
    return 0;
}


2.2 Deep Copy Constructor
Vậy khi ta muốn: Thay đổi đối tượng này sẽ không ảnh hưởng đến đ tượng kia?
Phương pháp Deep copy sẽ giúp ta giải quyết vấn đề,,,

Tương tự như ví dụ đầu tiên dùng cú pháp : tên class(const tên_class & tên_Object) {}

#include<iostream>
#include<cstring>
using namespace std;
class CopyConstructor
{
    char *s_copy;
    public:
    CopyConstructor (const char *str)
    {
        s_copy = new char[16];  //Dynamic memory alocation
        strcpy(s_copy, str);
    }
   
    CopyConstructor (const CopyConstructor &str)
    {
        s_copy = new char[16]; //Dynamic memory alocation
        strcpy(s_copy, str.s_copy);
    }
   
    void concatenate(const char *str)
    {
        strcat(s_copy, str); //Concatenating two strings
    }

    ~CopyConstructor()
    {
        delete [] s_copy;
    }

    void display()
    {
        cout<<s_copy<<endl;
    }
};
/* main function */
int main()
{
    CopyConstructor c1("Copy");
    CopyConstructor c2 = c1;    //copy constructor
    c1.display();
    c2.display();
    c1.concatenate("Constructor");    //c1 is invoking concatenate()
    c1.display();
    c2.display();
    return 0;
}


3. Hàm hủy
Cú pháp: ~[Tên class]
Hàm hủy không có tham số truyền vào.
Ví dụ:
class A
{
    public:
    // defining destructor for class
    ~A()
    {
        // statement
    }  
};


Ví dụ
class A
{
    // constructor
    A()
    {
        cout << "Constructor called";
    }
    // destructor
    ~A()
    {
        cout << "Destructor called";
    }
};
int main()
{
    A obj1;   // Constructor Called
    int x = 1
    if(x)
    {
        A obj2;  // Constructor Called
    }   // Destructor Called for obj2
} //  Destructor called for obj1

Vi du 2:
class Dual
{
    public:
    int a;
    Dual(int x=0)
    {
        a = x;
    }
};
int main()
{
    Dual obj1;
    Dual obj2(10);
}

Không có nhận xét nào:

Đăng nhận xét