现在的位置: 首页 > 综合 > 正文

C++学习笔记19 多态与继承

2016年02月04日 ⁄ 综合 ⁄ 共 2872字 ⁄ 字号 评论关闭

1:函数重写

如果子类当中定义了与父类当中原型相同的函数会怎么样?

函数重写:

在子类中定义与父类原型相同的函数;

函数重写只发生在父类与子类之间;

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

/*
函数重写: 
父类中被重写的函数依然会继承给子类
默认情况下子类中重写的函数将隐藏父类中的函数
通过作用域分辨符::可以访问到父类中被隐藏的函数
2014年9月3日19:51:11 
*/ 
#include <iostream> 
using namespace std;

class Parent
{
	public:
		void print()
		{
			cout<<"I'm a Parent"<<endl;
			
		}
};

class Child: public Parent
{
	public:
		void print()
		{
			cout<<"I'm a Child"<<endl;
			
		}
};

 
int main(int argc, char** argv) {
	
	Child child;
	child.print();//函数重写 
	child.Parent::print();
	
	return 0;
}

函数重写遇上赋值兼容性原则:

#include <iostream>

using namespace std;

class Parent
{
	public:
		void print()
		{
			cout<<"I'm a Parent"<<endl;
			
		}
};

class Child: public Parent
{
	public:
		void print()
		{
			cout<<"I'm a Child"<<endl;
			
		}
};

void run()
{
	
	Child child;
	Parent* pp = &child;
	Parent& rp = child;
	
	child.print();
	pp->print();
	rp.print();
} 
 
void howToPrint(Parent* p)
{
	p->print();
}
int main(int argc, char** argv) {
	
	cout<<"............................."<<endl;
	
	run();
	/*
C++与C相同,是静态编译型语言

在编译时,编译器自动根据指针的类型判断指向的是一个什
么样的对象

所以编译器认为父类指针指向的是父类对象(根据赋值兼容
性原则,这个假设合理)

由于程序没有运行,所以不可能知道父类指针指向的具体是
父类对象还是子类对象

从程序安全的角度,编译器假设父类指针只指向父类对象,
因此编译的结果为调用父类的成员函数
	
	*/
	cout<<"*******************************"<<endl;
	Parent *p;
	Child *q;
	
	howToPrint(p);//输出为  "I'm a Parent"
	howToPrint(q);//输出为  "I'm a Parent"
	/*
在编译这个函数的时候,编译器不可能知道指针 p 究
竟指向了什么。但是编译器没有理由报错。于是,编
译器认为最安全的做法是编译到父类的print函数,因
为父类和子类肯定都有相同的print函数。
	*/ 
	
	return 0;
}

 C++与C相同,是静态编译型语言
 在编译时,编译器自动根据指针的类型判断指向的是一个什
么样的对象
 所以编译器认为父类指针指向的是父类对象(根据赋值兼容
性原则,这个假设合理)
 由于程序没有运行,所以不可能知道父类指针指向的具体是
父类对象还是子类对象
 从程序安全的角度,编译器假设父类指针只指向父类对象,
因此编译的结果为调用父类的成员函数

 

由上面我们引出了多态:

面向对象的新需求
 根据实际的对象类型来判断重写函数的调用
 如果父类指针指向的是父类对象则调用父类中定义
的函数
 如果父类指针指向的是子类对象则调用子类中定义
的重写函数

面向对象中的多态:

根据实际的对象类型决定函数调用语句的具体调用目标;

多态:同样的调用语句有多种不同的表现形态;

p->print();

当p指向父类对象的时候,调用父类的print()函数;

当p指向子类对象的时候,调用子类的print()函数;

C++中的多态支持:

C++中通过virtual关键字对多态进行支持;

使用virtual声明的函数被重写后即可展现多态特性;

#include <cstdlib>
#include <iostream>

using namespace std;

class Boss
{
private:
	static Boss* cInstance;
	
	Boss()
	{
	}
	
public:
	static Boss* GetInstance()
	{
		if(cInstance == NULL)
		{
			cInstance = new Boss();
		}
		return cInstance;	
	}
	
	int fight()
	{
		cout<<"boss::fight()"<<endl;
		return 10;
	}
};

Boss* Boss::cInstance = NULL;
class Master
{
	
	public:
		virtual int eightSwordkill()
		{
			cout<<"Master::eightSwordkill()"<<endl;
			return 8;
		}
};

class NewMaster:public Master
{
	public:
		virtual int eightSwordkill()
		{
			cout<<"newMaster:: eightSwordKill()"<<endl;
			return Master::eightSwordkill()*2;
		}	
};

void fieldPK(Master* master, Boss* boss)
{
	
	int k = master->eightSwordkill();
	int b = boss->fight();
	if(k<b)
	{
		cout<<"Master is killed"<<endl;
	}
	else
	{
		cout<<"Boss is killed"<<endl;
	}
}

int main()
{

	Boss* boss = Boss::GetInstance();
	cout<<"Master VS Boss:"<<endl; 
	Master master;
	fieldPK(&master,boss);
	
	cout<<"newMaster VS Boss:"<<endl; 
	NewMaster newMaster;
	fieldPK(&newMaster,boss);
	
	cin.get();
}

/*

  多态的本质
面向对象的新需求
根据实际的对象类型来判断重写函数的调用
如果父类指针指向的是父类对象则调用父类中定义
的函数
如果父类指针指向的是子类对象则调用子类中定义
的重写函数


面向对象中的多态
根据实际的对象类型决定函数调用语句的具体调用目标
多态:同样的调用语句有多种不同的表现形态

C++中的多态支持
C++中通过virtual关键字对多态进行支持
使用virtual声明的函数被重写后即可展现多态特性

小结:
函数重写是面向对象中很可能发生的情形
函数重写只可能发生在父类与子类之间
需要根据实际对象的类型确定调用的具体函数
virtual关键字是C++中支持多态的唯一方式
被重写的虚函数即可表现出多态的特性

*/

 

抱歉!评论已关闭.