C++類相關總結-1

1. 虛函數的實現原理 ios

    在C++的類內會維護一個虛表,同時還有一個虛指針。能夠經過VC 6.0來觀看類的虛函數表。 網絡

#include <iostream>
#include <stdio.h>

class A{
public :
	virtual void f(){ std::cout<<"This is A's f"<<std::endl;};
	virtual void g(){ std::cout<<"This is A's g"<<std::endl;};
};

class B : public A{
public:
	B(){};
	void f(){ std::cout<<"This is B's f"<<std::endl;};
};

class C : public A{
public:
	void g(){ std::cout<<"This is C's g"<<std::endl;};
};

class D : public C,B{
public:
	void f(){ std::cout<<"This is D's f"<<std::endl;};
	void g(){ std::cout<<"This is D's g"<<std::endl;};
};

#define E_ss E::ss()

int main()
{
	A a;
	B b;
	C c;
	D d;

	std::cout<<"A's address is "<<&a<<std::endl;
	std::cout<<"B's address is "<<&b<<std::endl;
	std::cout<<"C's address is "<<&c<<std::endl;
	std::cout<<"D's address is "<<&d<<std::endl;

	return 0;
}

    

    C++的類中第一個變量就是虛指針。其中a類的地址是0x0012ff44,緊接着就是虛指針。而b類的地址爲0x0012ff40,因而可知a類內只有虛指針這一個變量。 函數

    

    解決了虛指針的問題,如今正式進入虛函數表。從代碼能夠看到,A類內定義了兩個虛函數 f() 和 g() ,B類繼承A類,實現了虛函數 f() ,並無實現 g() , C類正好相反。D類暫時不討論,她負責解釋多重繼承產生二義性的問題。 spa

    經過VC 6.0的調試能夠看到各個虛函數的地址,如圖。 指針

    

    能夠看到,a類的虛指針裏有兩個虛函數地址分別爲0x004012cd(A::f(void))和0x004011b8(A::g(void))。而b類繼承a類,因爲b類只實現了虛函數f(),因此b類的虛指針內的B::f(void)是指向b類內實現的虛函數,而g()函數仍是指向A類的A::g(void)函數。C類則與B類相似。 調試

    總結下,C++的類是經過一個虛指針(__vfptr)指向一個虛函數表來實現虛函數的功能,從而實現動態的多態。 code

2. 經過子類調用父類」們「方法 繼承

    依然是剛纔那段代碼,我在B、C、D類內分別寫了test(),來調用父類」們「的方法。 io

#include <iostream>
#include <stdio.h>

class A{
public :
	virtual void f(){ std::cout<<"This is A's f"<<std::endl;};
	virtual void g(){ std::cout<<"This is A's g"<<std::endl;};
};

class B : virtual public A{
public:
	void f(){ std::cout<<"This is B's f"<<std::endl;};
	void test()
	{
		std::cout<<"This is B's test"<<std::endl;
		A::f();
		A::g();
	}
};

class C : virtual public A{
public:
	void g(){ std::cout<<"This is C's g"<<std::endl;};
	void test()
	{
		std::cout<<"This is C's test"<<std::endl;
		A::f();
		A::g();
	}
};

class D : public C,B{
public:
	void f(){ std::cout<<"This is D's f"<<std::endl;};
	void g(){ std::cout<<"This is D's g"<<std::endl;};
	void test()
	{
		std::cout<<"This is D's test"<<std::endl;
		A::f();
		A::g();
		B::f();
		C::g();
	}
};

int main()
{
	A a;
	B b;
	C c;
	D d;

	b.test();
	c.test();
	d.test();

	return 0;
}

    

    在運行時對繼承方式作了修改,經過網絡圖和結果顯示。具體請看下圖。 class

            

            

            

    總結下,無論怎麼繼承子類均可以調用父類的方法,可是當子類B、C私有繼承類A時,類B、C的子類D則不能調用類A的方法。

相關文章
相關標籤/搜索