C++学习笔记(二十六)虚函数 多态 dynamic_cast

学习要点:

1 虚函数 根据对象类型来调用函数 而不是根据指针类型

2 子类中的与虚函数同名函数的都是虚函数

2013-5-5补充:

这个说法有点不准确:

(1) 如果必须参数列表和返回值函数名都相同 才能认为是对虚函数的重写,仍然是虚函数

(2)函数后面有const 和 无const,可以视为两种不同函数 ,这个必须和基类中一致才能视为虚函数

在这些不一致,或者说重写虚函数不成功的情况下,只会根据指针类型来调用.


3 dynamic_cast<子类*>(父类地址)的用法  把父类地址转化为子类地址

(1) 转化类型或者 地址 必须都是多态类型 (父类中有虚函数,但子类可以重写 也可以不重写 )

(2) 父类指针必须本来指向的是子类对象才能成功,否则返回NULL


#include <iostream>
#include <string>
using namespace std;
class Person
{
protected: 
	string name;
private: 
	bool gender;
public:
	Person(const char *name,bool gender):name(name),gender(gender){}
	void eat(const char* food) const
	{
		cout << name << "吃完了" << food << endl;
	}
	void sleep() const; //声明可以没有定义 前提是不调用它
	//虚函数 根据对象类型来调用函数 而不是根据指针类型
	virtual void talk() const
	{
		cout << "大家好,我是" << (gender?"帅哥":"美女") <<name
		<< ",很荣幸认识你!" << endl;
	}

	const string& Name()const
	{
		return name;
	}
};

class Teacher: public Person
{
	string course;
public:
	//若要初始化父类成员,在初始化列表中把参数传给父类的构造函数(只能在初始化列表中) 
	//初始化列表构造顺序不决定执行顺序
	Teacher(const char *name,bool gender,const char* course):Person(name,gender),course(course)
	{	
	}
	
	void teach(const char * _class) //class是关键字 不可以做变量名
	{
		cout << name << "老师在给" << _class << "讲" << course <<endl;
	}
		
	//这个是改写,不是重载,重载是同一层次的函数 参数表不同
	void talk() const 
	{
		cout << "同学们好,我是"<<  course <<"老师" << name
		<< ",希望能带领大家把" <<  course << "学好!"  <<endl;
	}
		
};
int main()
{
		Person a("芙蓉",false);
		Teacher b("权哥",true,"C++");
		Person *p=NULL,*q=NULL;
		p = &a;
		q =&b;
// 多态 : 如果希望在调用时根据对象的类型调用函数 要把该函数声明为虚函数
		p->talk(); //大家好,我是美女芙蓉,很荣幸认识你!
		q->talk(); //同学们好,我是C++老师权哥,希望能带领大家把C++学好!
		//使用父类指向子类时,若找不到函数 则会调用上一级的函数。
		//使用对象直接调用时,找不到就出错。
		
		Person c = b; //c将b多的部分截断
		c.talk(); //会调用Person中的函数。 //大家好,我是帅哥权哥,很荣幸认识你!

		Person &d = b; //引用的本质是指针 还是会根据对象类型找到函数
		d.talk(); //调用Teacher中talk函数。//同学们好,我是C++老师权哥,希望能带领大家把C++学好!
	
/*
	只有调用虚函数才会进行对象类型判断 并找到对象相应的函数
	普通函数会根据指针类型调用函数
			
	父类指针指向子类对象 父类对象 都可以。
	子类可以指向子类对象
	子类指针指向父类对象要看情况 需要检查下  
		
	dynamic_cast<子类*>(父类对象地址)      用来运行时 检查一个父类对象是否是子类对象 
	如果是: 返回一个正常地址,如果不是返回NULL	
	
	使用dynamic_cast 用来识别的前提是  基类中有虚函数
*/

	cout << dynamic_cast<Teacher*>(p)<<endl; //0
	cout << dynamic_cast<Teacher *>(q) <<endl;//0xbf91314c

	cout << dynamic_cast<Teacher*>(&c) <<endl; //0
	//并且这个地方有警告:warning: dynamic_cast of ‘Person c’ to ‘class Teacher*’ can never succeed
	//也就是说c本来就是Person类型的,永远可能转换为Teacher型。
	
	cout << dynamic_cast<Teacher *>(&d) <<endl;//0xbf91314c
	
}	


你可能感兴趣的:(C++学习笔记(二十六)虚函数 多态 dynamic_cast)