c++的虛函數

#include <stdio.h>

class Animal{
public:
	Animal(){};
	~Animal(){};

	void run(){printf("Animal is running!\n");}
	virtual void eat(){printf("Animal is eating!\n");}
	//有純虛函數的類稱爲抽象類, 其不允許被實例化
	//virtual void sleep() = 0;    //純虛函數,=0告訴編譯器函數沒有主體
	virtual void sleep(){printf("Animal is sleeping!\n");}
};

class Cat: public Animal{
public:
	Cat(){};
	~Cat(){};

	void run(){printf("Cat is running!\n");}
	void eat(){printf("Cat is eating!\n");}
	//void sleep(){printf("Cat is sleeping!\n");}
};

class Dog: public Animal{
public:
	Dog(){};
	~Dog(){};

	void run(){printf("Dog is running!\n");}
	void eat(){printf("Dog is eating!\n");}
	//void sleep(){printf("Dog is sleeping!\n");}
};

int main()
{
	Animal animal_one;
	Cat cat_one;
	Dog dog_one;
	animal_one.run();
	cat_one.run();
	dog_one.run();
	animal_one.eat();
	cat_one.eat();
	dog_one.eat();
	animal_one.sleep();
	cat_one.sleep();
	dog_one.sleep();
	printf("=====================\n");

	Animal *animal_two;
	Cat cat_two;
	Dog dog_two;
	animal_two->run();
	//animal_two->eat();   //段錯誤
	//animal_two->sleep(); //段錯誤
	animal_two = &cat_two;  //基類指針指向派生類對象
	animal_two->run();
	animal_two->eat();
	animal_two->sleep();
	animal_two = &dog_two;
	animal_two->run();
	animal_two->eat();
	animal_two->sleep();
	printf("=====================\n");

	Animal animal_three;
	Cat *cat_three;
	Dog *dog_three;
	cat_three = (Cat *)&animal_three;
	dog_three = (Dog *)&animal_three;
	animal_three.run();
	cat_three->run();
	dog_three->run();
	animal_three.eat();
	cat_three->eat();
	dog_three->eat();
	animal_three.sleep();
	cat_three->sleep();
	dog_three->sleep();

	return 0;
}

/*
運行結果:
Animal is running!
Cat is running!
Dog is running!
Animal is eating!
Cat is eating!
Dog is eating!
Animal is sleeping!
Animal is sleeping!
Animal is sleeping!
=====================
Animal is running!
Animal is running!
Cat is eating!
Animal is sleeping!
Animal is running!
Dog is eating!
Animal is sleeping!
=====================
Animal is running!
Cat is running!
Dog is running!
Animal is eating!
Animal is eating!
Animal is eating!
Animal is sleeping!
Animal is sleeping!
Animal is sleeping!
*/

/*
以下內容來自 https://www.jianshu.com/p/0e10fad538d6
1、初始化爲NULL的類指針可以安全調用不涉及類成員變量的類成員函數而不出錯,
但是如果類成員函數中調用了類成員變量則會出錯,既然賦值爲NULL的情況都可以使用,
那麼自然不初始化的類指針同樣滿足這類情況。
2、類中的函數被編譯器靜態編譯了,所有非虛函數都可以調用,因爲函數地址在編譯
期間已經確定。類中的成員函數都是通過this指針調用成員變量的,編譯器會將this指
針作爲默認參數傳給類成員函數的,如myclass.function(int a,int b) --> function(&myclass,int a,int b)
3、沒有調用成員變量的func()函數正確執行,調用了成員變量的get()函數錯誤。
兩者其實都傳入了空的this指針,前者沒出錯僅僅是因爲沒有調用this指針,而後者調用了。
調用成員函數的時候,函數地址是編譯期間確定的,成員函數不通過對象指針(也即當前的p指針)去調
用,對象指針僅僅作爲參數傳入函數然後去調用成員變量。
4、那如果是虛函數呢,因爲虛函數要通過this指針計算vptr,然後找到vtable,然後dispatch。
因爲this指針爲空,所以在找vtable時候就會coredump了。總之這類情況下,一切調用了this指針的函數
都會出錯,而完全不調用this指針的成員函數則沒問題。
以下內容來自http://c.biancheng.net/view/260.html
5、在公有派生的情況下,派生類的指針可以直接賦值給基類指針。但即便基類指針指向的是一個派生類的對象,
也不能通過基類指針訪問基類沒有而派生類中有的成員。
基類的指針不能賦值給派生類的指針。但是通過強制類型轉換,也可以將基類指針強制轉換成派生類指針後再賦值
給派生類指針。只是在這種情況下,程序員需要保證被轉換的基類指針本來就指向一個派生類的對象,這樣纔是安
全的,否則很容易出錯。
*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章