關於繼承

關於繼承

我們在前面已經有討論過解構式加上virtual的意義

我們將在這邊來討論一下

一般的成員函式加上virtual的意義

以下三個範例在main中都使用一樣的方式呼叫


int _tmain(int argc, _TCHAR* argv[])
{
Base* pBase = new Base();
pBase->fun_1(1);
pBase->fun_1();

Inherit* pInherit = new Inherit();
pInherit->fun_1(2);
pInherit->fun_1();


Base* pNewBase = static_cast<Base*>(pInherit);
pNewBase->fun_1(3);
pNewBase->fun_1();


delete pInherit;
delete pBase;

return 0;
}

 

首先這個範例在編譯時是會失敗的

pInherit->fun_1(2); 這一行會找不到對應的函式

#include "stdafx.h"
#include <iostream>

class Base
{
public:
Base(){}
virtual ~Base(){}
void fun_1()
{
std::cout << "Base fun_1" << std::endl;
}

void fun_1(int a)
{
std::cout << "Base fun_1 a=" << a << std::endl;
}

};

class Inherit : public Base
{
public:
Inherit(){}
~Inherit(){}

void fun_1()
{
std::cout << "Inherit fun_1" << std::endl;
}
};

 

 

 

 

 

如果真要在繼承的物件中取與父系相同的函式名稱的話

必須要在子系的物件中加上 using Base::fun_1;

#include "stdafx.h"
#include <iostream>

class Base
{
public:
Base(){}
virtual ~Base(){}
void fun_1()
{
std::cout << "Base fun_1" << std::endl;
}

void fun_1(int a)
{
std::cout << "Base fun_1 a=" << a << std::endl;
}

};

class Inherit : public Base
{
public:
using Base::fun_1;

Inherit(){}
~Inherit(){}

void fun_1()
{
std::cout << "Inherit fun_1" << std::endl;
}
};

但是這樣會發生什麼事情呢

我們看一下輸出的結果

image

很明顯的

當我們要呼叫 pNewBase->fun_1(); 的時候

被執行的是父系物件中的fun_1()

這在程式執行的時候

是一件很危險的事情

 

 

接下來我們在父系的fun_1()前面加入virtual

#include "stdafx.h"
#include <iostream>

class Base
{
public:
Base(){}
virtual ~Base(){}
virtual void fun_1()
{
std::cout << "Base fun_1" << std::endl;
}

void fun_1(int a)
{
std::cout << "Base fun_1 a=" << a << std::endl;
}

};

class Inherit : public Base
{
public:
using Base::fun_1;

Inherit(){}
~Inherit(){}

virtual void fun_1()
{
std::cout << "Inherit fun_1" << std::endl;
}
};


這樣一來每個成員函式才有對應到我們應該要輸出的結果

image