[OOP] Con trỏ và tham chiếu của Base class đến đối tượng Derived

Trong bài kế thừa trong C++ ta đã biết khi tạo 1 đối tượng của class Derived sẽ gọi constructor của Base class trước sau đó mới gọi đến constructor của Derived class.

Mặt khác kế thừa thể hiện mối quan hệ is-a của 2 class. Khi đó Derived is-a Base. Vì thế trong C++ cho phép ta tạo con trỏ, tham chiếu của Base class đến đối tượng Derived.

Ví dụ:


#include <iostream>

#include <string>

using namespace std;

class Base

{

public:

   void Info()

   {

      cout << "This is base class!" << endl;

   }

};

class Derived : public Base

{

public:

   void Info()

   {

      cout << "This is derived class!" << endl;

   }

   void DerivedFunc()

   {

      cout << "This function only Derived!" << endl;

   }

};

int main()

{

   Derived derived;

   Base& refBase = derived;

   Base* ptrBase = &derived;

   derived.Info();

   refBase.Info();

   ptrBase->Info();

   return 0;

}

Kết quả:

This is derived class!
This is base class!
This is base class!

Vì refBase và ptrBase là reference và con trỏ của Base class nên nó chỉ có thể nhìn thấy cách thành phần của Base class. Mặc dù hàm Derived::Info che đi hàm Base::Info cho đối tượng của Derived nhưng refBase và ptrBase vẫn không thể thấy hàm Derived::Info. Nên nó sẽ gọi hàm Base::Info.

Ta cũng không thể gọi hàm DerivedFunc thông qua refBase/ptrBase.

Qua ví dụ trên ta tự hỏi:

Tại sao không tạo luôn tham chiếu, con trỏ của Derived mà phải tạo của Base?

Ta cùng xét ví dụ tiếp


#include <iostream>

#include <string>

using namespace std;

class Animal

{

public :

   void Speak()

   {

      cout << "None" << endl;

   }

};

class Dog : public Animal

{

public:

   void Speak()

   {

      cout << "Gau gau" << endl;

   }

};

class Cat

{

public:

   void Speak()

   {

      cout << "Meo meo" << endl;

   }

};

void Info(Dog& dog)

{

   dog.Speak();

}

void Info(Cat& cat)

{

   cat.Speak();

}

int main()

{

   Dog dog;

   Info(dog);

   Cat cat;

   Info(cat);

   return 0;

}

Ở trên để in ra thông tin của mỗi con vật, ta phải viết hàm với tham số là con vật cần in thông tin. Nó sẽ rất bất tiện và khó khăn nếu số lượng con vật muốn in thông tin lớn. Tuy nhiên ta nhận thấy các con vật (Dog, Cat) đều được kế thừa từ Animal, ta có thể sử dụng hàm với tham số là tham tham chiếu hoặc con trỏ của Animal.


void Info(Animal& animal)

{

   animal.Speak();

}

Dog dog;

Animal& rAmimal = dog;

Info(rAmimal);

Tuy nhiên đến đây xảy ra vấn đề rAmimal là reference của Animal nên nó sẽ gọi hàm Speak của Animal, nó không gọi chính xác được hàm Speak của lớp dẫn suất (Dog, Cat). Để giải quyết vấn đề này C++ cung cấp cho ta virtual function để reference, con trỏ của lớp cơ sở gọi đuợc hàm của lớp dẫn suất.

Was this article helpful?

Leave A Comment?