Đa năng hóa toán tử trong Lập trình hướng đối tượng (Phần 2)

Nhưng đối với các kiểu do người dùng định nghĩa thì trình biên dịch không thể tự động biết làm thế nào chuyển đổi trong số các kiểu dữ liệu do người dùng định nghĩa và các kiểu có sẵn. Lập trình viên phải chỉ rõ làm sao các chuyển đổi như vậy sẽ xuất hiện. Các chuyển đổi như thế có thể được thực hiện với constructor chuyển đổi.

Các toán tử new delete toàn cục có thể được đa năng hóa. Điều này cho phép các lập trình viên C++ có khả năng xây dựng một hệ thống cấp phát bộ nhớ theo ý người dùng, cói cùng giao tiếp như hệ thống cấp phát mặc định.

Có hai cách đa năng hóa các toán tử newdelete:

  • Có thể đa năng hóa một cách toàn cục nghĩa là thay thế hẳn các toán tử new delete mặc định.
  • Chúng ta đa năng hóa các toán tử newdelete với tư cách là hàm thành viên của lớp nếu muốn các toán tử newdelete áp dụng đối với lớp đó. Khi chúng ta dùng newdelete đối với lớp nào đó, trình biên dịch sẽ kiểm tra xem newdelete có được định nghĩa riêng cho lớp đó hay không; nếu không thì dùng newdelete toàn cục (có thể đã được đa năng hóa).

Hàm toán tử của toán tử newdelete có prototype như sau:

void * operator new(size_t size);
    void operator delete(void * ptr);
    

Trong đó tham số kiểu size_t được trình biên dịch hiểu là kích thước của kiểu dữ liệu được trao cho toán tử new.

Đa năng hóa toán tử new và delete toàn cục

Ví dụ 4.15: Đa năng hóa toán tử newdelete toàn cục đồng thời chứng tỏ rằng toán tử newdelete do đa năng hóa thay thế toán tử newdelete mặc định.

1: #include <iostream.h> 
    2: #include <stdlib.h>
    3:
    4: class Point
    5: {
    6: private:
    7: int X, Y;
    8: public:
    9: Point(int A=0,int B=0)
    10: {
    11: X=A;
    12: Y=B;
    13: cout<<"Constructor!"<<endl;
    14: }
    15: ~Point()
    16: {
    17: cout<<"Destructor!"<<endl;
    18: }
    19: void Print() const
    20: {
    21: cout<<"X="<<X<<","<<"Y="<<Y<<endl;
    22: }
    23: };
    24:
    25: void * operator new(size_t Size)
    26: {
    27: return malloc(Size);
    28: }
    29:
    30: void operator delete(void *Ptr)
    31: {
    32: free(Ptr);
    33: }
    34:
    35: int main()
    36: {
    37: Point *P1,*P2;
    38: P1= new Point(10,20);
    39: if (P1==NULL)
    40: {
    41: cout<<"Out of memory!"<<endl;
    42: return 1;
    43: }
    44: P2= new Point(-10,-20);
    45: if (P2==NULL)
    46: {
    47: cout<<"Out of memory!"<<endl;
    48: return 1;
    49: }
    50: int *X=new int;
    51: if (X==NULL)
    52: {
    53: cout<<"Out of memory!"<<endl;
    54: return 1;
    55: }
    56: *X=10;
    57: cout<<"X="<<*X<<endl;
    58: cout<<"Point 1:";
    59: P1->Print();
    60: cout<<"Point 2:";
    61: P2->Print();
    62: delete P1;
    63: delete P2;
    64: delete X;
    65: return 0;
    66: }
    

Chúng ta chạy ví dụ 4.15, kết quả ở hình 4.20

Kết quả của ví dụ 4.15 (Hình 4.20)

Đa năng hóa toán tử new và delete cho một lớp

Nếu muốn toán tử newdelete có tính chất đặc biệt chỉ khi áp dụng cho đối tượng của lớp nào đó, chúng ta có thể đa năng hóa toán tử newdelete với tư cách là hàm thành viên của lớp đó. Việc này không khác lắm so với cách đa năng hóa toán tử newdelete một cách toàn cục.

Ví dụ 4.16: Đa năng hóa toán tử new và delete cho một lớp.

1: #include <iostream.h> 
    2: #include <stdlib.h>
    3: class Number
    4: {
    5: private:
    6: int Data;
    7: public:
    8: Number(int X=0)
    9: {
    10: Data=X;
    11: }
    12:
    13: void * operator new(size_t Size)
    14: {
    15: cout<<"Toan tu new cua lop!"<<endl;
    16: return ::new unsigned char[Size];
    17: }
    18:
    19: void operator delete(void *Ptr)
    20: {
    21: cout<<"Toan tu delete cua lop!"<<endl;
    22: ::delete Ptr;
    23: }
    24:
    25: void Print() const
    26: {
    27: cout<<"Data:"<<Data<<endl;
    28: }
    29:
    30: };
    31:
    32: int main()
    33: {
    34: Number *N;
    35: N= new Number(10);
    36: if (N==NULL)
    37: {
    38: cout<<"Out of memory!"<<endl;
    39: return 1;
    40: }
    41: int *X=new int;
    42: if (X==NULL)
    43: {
    44: cout<<"Out of memory!"<<endl;
    45: return 1;
    46: }
    47: *X=10;
    48: cout<<"X="<<*X<<endl;
    49: N->Print();
    50: delete N;
    51: delete X;
    52: return 0;
    53: }
    

Chúng ta chạy ví dụ 4.16, kết quả ở hình 4.21

Kết quả của ví dụ 4.16 (Hình 4.21)