- Back to Home »
- CPP »
- C++ Polymorphism
Saturday, May 2, 2015
1. Polymorphism
Đa hình là cách mà implement một function member trong base class, cách mà function member đó được redefine trong derived class như thế nào. Đa hình liên quan đến các khái niện inheritance, virtual function
Ex
polymorphism.cpp
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// Main function for the program
int main( )
{
Shape *ps;
Shape shape(10, 11);
Rectangle rec(10,7);
Triangle tri(10,5);
// store the address of Shape
ps = &shape;
// call shape area.
ps->area();
// store the address of Rectangle
ps = &rec;
// call rectangle area.
ps->area();
// store the address of Triangle
ps = &tri;
// call triangle area.
ps->area();
return 0;
}
Compile & Execute:
$ g++ polymorphism.cpp
$ ./a.out
Parent class area :
Parent class area :
Parent class area :
Khi chạy thấy print kết quả ra sai, đáng lý ra kết quả đúng phải là Parent-Rectange -Triangle mới đúng, lý do sai là vì compiler sẽ thực hiện biên dịch một lần duy nhất khi gặp hàm area( ) trong base class, các hàm area( ) khác trong derived class bị bỏ qua.
Để khắc phục điều này thì cần khai báo thêm từ khóa virtual trước hàm area( ), chính điều này tạo ra tính đa hình trong C++
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
Compile & Execute:
$ g++ polymorphism.cpp
$ ./a.out
Parent class area :
Rectangle class area :
Triangle class area :
2. Virtual function
Hàm ảo là hàm được khai báo và implement trong base class sử dụng với từ khóa virtual, và hàm này được re-implement lại trong derived class. Như ví dụ trên thì hàm
virtual int area( ) chính là một hàm ảo.
3. Pure virtual function
Hàm thuần ảo cũng được khai báo với từ khóa virtual nhưng nó lại không được implement trong base class, điều đó dẫn đến nó bắt buộc phải được implement trong derived class.
Ex
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;
};
Note: Một hệ quả là không thể tạo ra object từ base class.
Xét vd trên khi compile đến đoạn khai báo
Shape shape(10, 11);
thì sẽ bị lỗi.Ex
pure-virtual-function.cpp
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area() = 0;
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// Main function for the program
int main( )
{
Shape *ps;
Rectangle rec(10,7);
Triangle tri(10,5);
// store the address of Rectangle
ps = &rec;
// call rectangle area.
ps->area();
// store the address of Triangle
ps = &tri;
// call triangle area.
ps->area();
return 0;
}
Compile & Execute
$ g++ pure-virtual-function.cpp
$ ./a.out
Rectangle class area :
Triangle class area :
4. Virtual Destructor
Hàm hủy ảo là một destructor được khai báo dạng virtual function, có tác dụng đảm bảo cho việc thực hiện hàm hủy đúng thứ tự khi giải phóng một object thuộc derived class.
+ Khi khởi tạo (new) một object của derived class thì sẽ lần lượt gọi base constructor rồi đến derived constructor
+ Khi giải phóng (delete) một object của derived class thì sẽ lần lượt gọi derived destructor rồi mới đến base destructor
Ex:
virtual-destructor.cpp
#include <iostream>
using namespace std;
class Base
{
public:
Base(){
cout<<"Constructor: Base"<<endl;
}
virtual ~Base(){
cout<<"Destructor : Base"<<endl;
}
};
class Derived: public Base
{
//Doing a lot of jobs by extending the functionality
public:
Derived(){
cout<<"Constructor: Derived"<<endl;
}
~Derived(){
cout<<"Destructor : Derived"<<endl;
}
};
int main()
{
Base *Var = new Derived();
delete Var;
}
Compile & Execute:
$ g++ virtual-destructor.cpp
$ ./a.out
Constructor: Base
Constructor: Derived
Destructor : Derived
Destructor : Base
Thử trong trường hợp không có virtual ở base class sẽ đươc kết quả sai như dưới
$ g++ virtual-destructor.cpp
$ ./a.out
Constructor: Base
Constructor: Derived
Destructor : Base
Note: Vì lý do trên nên tốt nhất là luôn khai báo destructor là virtual destructor ở cả base class lẫn derived class