`

【C++ Primer】类的多态

 
阅读更多

一,概述

1)接口的多种不同的实现方式即为多态。

2)多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在C++中都是通过虚函数(Virtual Function) 实现的。

3)关键点:多态还有个关键之处就是一切用指向基类的指针或引用来操作对象


二,示例

1)普通的对象操作方式

#include <iostream>
using namespace std;
class A{
public:
	void print()
	{ 
		cout<<"This is A"<<endl;
	} 
};
class B:public A{
public:
	void print()
	{ 
		cout<<"This is B"<<endl;
	}
};
int main(){ //为了在以后便于区分,我这段main()代码叫做main1  
	A a; 
	B b; 
	a.print();
	b.print();
}

输出:This is A

This is B

2)按照多态的操作对象方式:通过父类对象来操作子类对象

#include <iostream>
using namespace std;
class A{
public:
	void print()
	{ 
		cout<<"This is A"<<endl;
	} 
};
class B:public A{
public:
	void print()
	{ 
		cout<<"This is B"<<endl;
	}
};
int main(){ //通过父类来操作子类 
	A a; 
	B b; 
	A* p1=&a;
	A* p2=&b;
	p1->print();
	p2->print();
}

输出:This is A

This is A

这跟我们预期的不一样


3)采用多态,就是在父类函数前面加上virtual

根据不同的类对象,调用其相应的函数,这个函数就是虚函数

#include <iostream>
using namespace std;
class A{
public:
	virtual void print()
	{ 
		cout<<"This is A"<<endl;
	} 
};
class B:public A{
public:
	void print()
	{ 
		cout<<"This is B"<<endl;
	}
};
int main(){ //通过父类来操作子类 
	A a; 
	B b; 
	A* p1=&a;
	A* p2=&b;
	p1->print();
	p2->print();
}

三,虚函数进阶

void (A::*fun)(); //定义一个函数指针   
A *p=new B;
fun=&A::fun;//是真正获得虚函数的地址吗? 其实间接获得虚函数地址的一段代码的地址

#include <iostream>
using namespace std;

class A{ 
public:
	virtual void fun()
	{ 
		cout<<"A::fun"<<endl;
	}
	virtual void fun2()
	{
		cout<<"A::fun2"<<endl;
	}
}; 
class B:public A{
public:
	void fun()
	{ 
		cout<<"B::fun"<<endl;
	}
	void fun2()
	{
		 cout<<"B::fun2"<<endl;
 	}
}; 
void CallVirtualFun(void *pThis , int  index=0)
{
	void (*funptr)(void*);
	long lVptrAddr;
	memcpy(&lVptrAddr,pThis,4);
	memcpy(&funptr,reinterpret_cast<long*>(lVptrAddr)+index,4);
	funptr(pThis); 
} 
int main()
{

	void (A::*fun)(); //定义一个函数指针   
	A *p=new B;
	fun=&A::fun;//是真正获得虚函数的地址吗? 其实间接获得虚函数地址的一段代码的地址
	(p->*fun)();//B::fun 
	fun = &A::fun2;
	(p->*fun)();//B::fun2
	 
    CallVirtualFun(p); //调用虚函数p->fun() 
	CallVirtualFun(p,1);//调用虚函数p->fun2() 
	delete p;
	system("pause");
	return 0; 
} 

四,补充重要知识

实例化类的虚函数必须有定义,原因如下:有虚函数作为成员函数的类, 它的实例化-对象, 在运行过程分配到的内存不止是它的成员数据, 还有一个指向该类虚函数表(vtable)的指针, 虚函数表中的每个数据项都是一个虚函数的入口地址;

如果一个对象的虚函数只有声明而没有实现, 就会出现这个虚函数表找不到本应作为其数据项之一的某函数的入口地址, 虚函数表在运行前不能装载完成, 所以产生连接错误!








分享到:
评论

相关推荐

    C++ primer中文版.pdf

    进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计,因而C++就适应的问题规模而论,大小由之。 [1] C++不仅拥有计算机高效运行的实用性特征,同时还致力...

    C++ Primer中文第三版版

    C++是C语言的继承,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于...

    C++面向对象程序设计-多态

    继承呼唤多态、虚函数、纯虚函数与抽象类、静态联编、动态联编

    C++Primer第四版英文版

    分别介绍了C++程序的运行方式、基本数据类型、复合数据类型、循环和关系表达式、分支语句和逻辑操作符、函数重载和函数模板、内存模型和名称空间、类的设计和使用、多态、虚函数、动态内存分配、继承、代码重用、...

    C++ Primer第四版 中文版(第一卷)

    分别介绍了C++程序的运行方式、基本数据类型、复合数据类型、循环和关系表达式、分支语句和逻辑操作符、函数重载和函数模板、内存模型和名称空间、类的设计和使用、多态、虚函数、动态内存分配、继承、代码重用、...

    自学编程语言资料合集2

    分别介绍了C++程序的运行方式、基本数据类型、复合数据类型、循环和关系表达式、分支语句和逻辑运算符、函数重载和函数模板、内存模型和名称空间、类的设计和使用、多态、虚函数、动态内存分配、继承、代码重用、...

    程序员面试刷题的书哪个好-CPP_Learning:记录下C++语言学习

    C++多态,虚函数机制 基础:继承关系,有虚函数,父类指针指向子类。虚函数表 进程通信 进程线程差异 进程是最小的资源分配单位,线程是最小的CPU控制分配单元 TCP三次握手四次挥手细节 说的越完整越好 算法题:最长...

    软件工程工具书.docx

    (C语言之父不是谭浩强) C Primer Plus 第五版 C++ Primer Plus 第五版 C++编程思想 总感觉没有Java编程思想那样出色。 提高: C陷阱与缺陷 C与指针 如果C程序员只能选择两本书,第二本就是这个了。 第一本?第一本...

    cppPrimerPlus-six--master.zip

    C++是在C语言基础上开发的一种集面向对象编程、通用编程和传统的过程化编程于一体的编程语言,是...他撰写的The Waite Group's C++Primer Plus一书获得了计算机出版联合会1991年度最佳“How-to”计算机图书奖的提名。

    C++常用特性原理解析

     这篇笔记从G++编译出的汇编代码出发,对部分C++的常用面向对象特性进行原理性解释和总结,其中包括 引用、类(成员函数,构造函数)、多态(编译时,运行时)、模板与泛型  Here we go!  引用  这是一个...

Global site tag (gtag.js) - Google Analytics