繼承那些坑

baby的我發表於2020-09-25

使用父類的引數呼叫子類的函式


#include <iostream>
using namespace std;

class A
{
	public:
		virtual void fun(int a = 1)
		{
			cout << "A->" << a << endl;
		}

		virtual void test()
		{
			fun();
		}
};

class B : public A
{
	public:
		virtual void fun(int a = 0)
		{
			cout << "B->" << a <<endl;
		}
};

int main()
{
	B * p = new B;
	p->test(); //B->1
	return 0;
}

子類指標p指向子類,

但沒有實現父類的虛擬函式test,所以呼叫父類的虛擬函式test()

test()將會使用父類的引數呼叫子類的函式fun(),所以輸出B->1

 

虛解構函式


為什麼要將基類的解構函式定義為虛擬函式?

當使用基類指標指向子類時,

如果delete這個指標,就只會呼叫基類的解構函式,可能會造成記憶體洩漏

如果將基類的解構函式設定為虛擬函式,那麼delete這個指標會先呼叫子類的解構函式,再呼叫父類的解構函式。

 

建構函式執行順序


一個A類繼承B類,且其成員包含C類的物件c,

class A : public B
{
	public:
		A();
		
	private:
		C c
};

那麼在使用A類建立物件是,會先執行B的構造,再執行C的構造,再執行A自己的構造。

 

父類指標操作子類


#include <iostream>
using namespace std;

class A
{
	public:
		long a;
};
class B : public A
{
	public:
		long b;
};


void seta(A* data, int idx)
{
	data[idx].a = 2;
}


int main(int argc, char *argv[])
{
	B data[4];
	for(int i=0; i<4; ++i)
	{
		data[i].a = 1;
		data[i].b = 1;
		seta(data, i);
	}
	
	for(int i=0; i<4; ++i)
	{
		std::cout << data[i].a << data[i].b; // 22221111
	}
	
	return 0;
}

先宣告瞭子類陣列data,然後傳入seta,此時data將會轉換為父類指標,

而父類佔4個位元組,子類佔8個位元組,就會將子類的成員也給改變。

 

 

 

 

 

相關文章