社区
C++ 语言
帖子详情
对多态的概念不能很好的理解。
AllanJD
2003-12-10 02:34:32
多态的概念许多书上都讲得很模糊,我实在是不好理解。
希望有高手能帮我一下啊!
谢谢!
...全文
47
9
打赏
收藏
对多态的概念不能很好的理解。
多态的概念许多书上都讲得很模糊,我实在是不好理解。 希望有高手能帮我一下啊! 谢谢!
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
9 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
AllanJD
2003-12-10
打赏
举报
回复
由(流星雨)的回复,
形状类有DRAW方法,在派生出不同的形状的时候DRAW方法对应的代码是不同的是吗?
那么,我在定义形状类的时候怎么写代码呢?他对派生出来的每种形状都有不同的功能啊!
langzi8818
2003-12-10
打赏
举报
回复
哦 ,有人给贴铁出来啦 !
computer386
2003-12-10
打赏
举报
回复
比如你定义了一个形状类,他有一个方法,命名为Draw吧,在他的基础上,你又派生出矩形,三角形,圆形等等。由于他们是派生自形状类,所以他们也都有Draw方法,当你让矩形Draw时,他画的是矩形,当你让三角形Draw时,他画的是三角形,调用的是同一个方法,但各个对象执行的却是他们自己的方法,不会你调用矩形的Draw时,他画除了一个三角形。这就叫多态。
byyyyy
2003-12-10
打赏
举报
回复
理解C++面向对象编程[多态性部分]
面向对象编程
初次写文章,错误一定百出不止。我只是希望我学习面向对象编程的一些理解看法
能对有关有共同爱好的人有一些小小用处,还谈不上帮助。
[文本涉及称谓说明]
1.变量:这个称谓包括两个部分。
内建类型实例(比如int,float,char等)
用户自定义类型实例(比如类(class),联合(union),结构(struct)等)
同时本文有时候也泛泛的称变量和函数为程序成员.
2.父类/子类: 相对于继承层次而言,被继承的为父类;继承的为子类.
3.对象: 本文指类类型的实例(an instance of a class)
************************************基础部分**************************
[内存对象模型概要]
因为本文主要是讨论多态性在语言层面上的表现,所以我这里不打算做太深入的
讨论,只是为了本文的阐释目的,做一些针对性的说明,概念性解释一下内存对象模型。
C++类类型的成员函数,我们可以把他们看成C语言中函数。它只是被编译器进行
一定的相关处理防止命名冲突而已。同时除了类中静态成员函数以外,这些函数
比普通的C语言函数增加了一个参数(this指针),因为可以处理对象中成员变量。
所以我们并没有在class的对象内存布局中看到任何与成员函数有关的东西。
当然要是类声明中或者类的继承层次中出现virtual函数的话,你会在内存布局中看到
有一个叫“虚拟函数指针表”的东东的存在。当我们不是使用单一继承的话,情况变得
更加复杂了,正如前面所讲的那样,本文主要在解释如何在语言使用层面上使用语言,
因此我不会在这里谈论更多关于内存布局的内容,需要了解的同行,请自行参阅有关
面向对象编程的书籍。
[程序成员生命周期概要]
存储空间:定义程序成员在程序中(或者翻译单元中)的存储形式.正如我们经常遇到的那样,
有很多程序全局变量,程序局部变量等等概念.同时这个概念决定了变量的生命
周期.这个概念主要指出了变量放在程序运行的哪个内存部分,比如说程序数据段,
程序栈等等.
生命周期:程序成员在那个时间段是可以利用的,简单一点讲就是程序运行中有一段时间某个成员
是可以引用的,我们就把这段时间称为这个成员的生命周期.
可见性:哪些界面(类,函数)可以引用程序成员
链接方式:概念是指一个翻译单元中声明定义成员是否可以被程序的其他的翻译单元使用.
************************************理论部分**************************
[重要的三个结论]
为了说明结论引入类:
class CBase
{
public:
BaseFunc(){}
};
class CDerived :public CBase
{
public:
DeriFunc(){}
};
☆结论一☆.如果我们以一个[父类指针]pointer指向一个[子类对象],那么通过pointer我们
只能呼叫引用父类类型(指类定义)中所定义的函数.
我们这样写:
CBase* pBase;
虽然我们可以用指针pBase指向CDerived对象,但是由于
pBase是一个CBase类型指针,所以我们只能呼叫(或引用)
BaseFunc(),不能DeriFunc()。
☆结论二☆. 如果我们以一个[子类指针]指向一个[父类对象],我们引用函数前,必须通过RTTI来
确定指针指向对象的具体类型.也就是说要做显式的造型转换.这种做法应该是我们做
程序员深恶痛绝的做法.
CDerived* pDeri;
CDerived *pDeri;
CBase aBase("Jason");
pDeri = &aBase;
☆结论三☆. 如果父类和子类都定义了[相同名称的成员函数],我们这个时候通过指针呼叫
引用成员函数的决议,就必须根据指针类型(注意不是指针实际指向对象的类型)
来确定我们引用的是哪个函数.实际上这个结论就是函数屏蔽(mask)功能,这个结论很重要的,
因为这里不管是不是虚拟函数,统统管用的,所以这个结论杀伤力很大的,后面我重点
解释这个结论。
************************************解释部分**************************
☆结论一解释☆:
为什么是这样的,我们下面看一下一个例子来了解为什么语言设计者采用这样的策略呢?
#include <iostream.h>
#include <stdio.h>
class ClassA
{
public:
int m_data1;
void func1() { }
void func2() { }
virtual void vfunc1() { }
virtual void vfunc2() { }
};
class ClassB : public ClassA
{
public:
int m_data2;
void func2() { }
void func3(){}
virtual void vfunc1() { }
};
当我们写这样的一下函数;
看看这个函数实现方面有那些问题呢?
void change(ClassA& ca)
{
ca.func1();
ca.func2();
//ca.func3();
ca.vfunc1();
ca.vfunc2();
}
当我们这样调用函数:
ClassA ca;
ClassB cb;
/*
调用说明,当我们这样调用的时候,大家应该都很明白的发现
那个func3()函数是不能调用的,因为这个函数在ClassA中根本
就是不存在的。很简单吧,但是复杂的问题本身就是很简单的,
我们继续下面一个例子
*/
change(ca);
/*
你也许说这样应该可以调用func3()函数了吧,不错ClassB中的确是
存在一个名字叫func3()的函数,但是我们仍然不能通过上面那个函数
调用他的,为什么呢?请接着看我下面的解释
*/
change(cb);
/*
因为我们是用一个父类的引用引用一个子类的类型的。
从函数的实现细节,我们的目的很明确的,就是要实现
多态性,因为我们在函数使用的时候才能知道函数参数
引用指向对象的真正类型,可能是ClassA也可能是ClassB的,
当然我们就不能贸然的调用func3()那个函数了。我们我们
那样实现函数在编译器的时候就会被挡住了。
☆结论二☆
这个结论属于程序员编程的能力问题,因为语言提供了灵活性,但是
如何使用是程序员本身的事情,如果你没有很好的理解语言本身,你
写的代码就是经常会出现问题,这个只能怪我们自己,要进修,绝对
不要动辄就说这个语言不好。
*********************本人废话集***************************
很多语言都讲什么简单简洁的,我在这里讲一个不是很生动的例子,
看过这个例子以后,我不知道你对于那些所谓简洁的语言的看法会
有什么改变。呵呵~~~~
经常同行人讲某某企业公司太没有自由了,严重影响自己创造性之类的话。
你想过这些话没有?我来说我的理解,如果这位同行换一家比较自由的公司,
按理讲,他的创造性应该可以得到一定程序的释放(就是发挥了)。
这个就是自由度从小到大给我带来的好处。
同时由于我们这个同行还是以为严格要求自己的人,所以他即使在自由度很大的
空间中也可以很好的把握自己的方向。
好了,中常休息的时间差不多结束了。现在回到正题,一个给程序员自由度很大的
语言,我们称为灵活性比较高的语言。在这样的语言环境中,我们并不是每一个都
可以很好利用这个灵活性的,有时候造成错误发生,但是我们不应该责怪语言本身,
我们需要做的只有一件事情,就是努力提高自己的水平。
而自由度很低的语言,我们就丧失了这种灵活性,我们再想扩大自由度的时候已经
有些不太可能的。但是我们为了获得在自由度大的环境下自由毒比较小的时候,我们
只要严格要求自己就行了。
上面的废话我是建立在程序员就是程序员本身,程序员不是编程机器的基础之上的。
无论如何软件生产不会(至少说几使年之内),象传统生产行业那样的,何况现在
已经进入“人管理“(知识管理)时代。
**********************************************************
☆结论三☆
说到这个结论,实际上就是C++中与override ,overload齐名的mask问题了。
借助上面的分析我们一口气把这个问题也弄明白。
我这个例子和解释是借用<<effective C++>>,特此说明。
不过这里也加入我的一些说明,这样我觉得很容易理解。
下面看一个可能使你会发疯的例子。
class Base {
public:
void f(const Base& base){}
virtual void f(int x){}
};
class Derived: public Base {
public:
virtual void f(double *pd);
};
Derived *pd = new Derived;
pd->f(10); // 错误!
这里就发生了函数屏蔽作用,你要是不清楚的话,请你再次看一下上面的结论三。
这不很合理,但ARM对这种行为提供了解释。假设调用f时,你真的是想调用Derived中的版本,但不小心用错了参数类型。进一步假设Derived是在继承层次结构的下层,你不知道Derived间接继承了某个基类BaseClass,而且BaseClass中声明了一个带int参数的虚函数f。这种情况下,你就会无意中调用了BaseClass::f,一个你甚至不知道它存在的函数!在使用大型类层次结构的情况下,这种错误会时常发生;所以,为了防患于未然,Stroustrup决定让派生类成员按名字隐藏掉基类成员。
顺便指出,如果想让Derived的用户可以访问Base::f,可以很容易地通过一个using声明来完成:
class Derived: public Base {
public:
using Base::f; // 将Base::f引入到
// Derived的空间范围
virtual void f(double *pd);
};
Derived *pd = new Derived;
pd->f(10); // 正确,调用Base::f
对于尚不支持using声明的编译器,另一个选择是采用内联函数:
class Derived: public Base {
public:
virtual void f(int x) { Base::f(x); }
virtual void f(double *pd);
};
Derived *pd = new Derived;
pd->f(10); // 正确,调用Derived::f(int),
// 间接调用了Base::f(int)
AllanJD
2003-12-10
打赏
举报
回复
我还没得到答案啊!自己顶一下。
期待。
AllanJD
2003-12-10
打赏
举报
回复
楼上的朋友说的这个我也不好理解啊!
能不能说得详细一点啊?
谢谢!
hanyixin
2003-12-10
打赏
举报
回复
这个是什么书上讲的?
不同的函数就是在相同的类上也会有不同的行为。
多态是说相同的函数在不同的类上会有不同的行为。
AllanJD
2003-12-10
打赏
举报
回复
不懂什么叫做“不同的函数在不同的类上有不同的行为”,这是什么意思啊?
盼望指点,关注!
hanyixin
2003-12-10
打赏
举报
回复
高手讲的不会比书上讲的清楚了 ^_^
从底层汇编
理解
C++
多态
原理
这门课的初衷就是让大家能够从汇编的角度看
多态
实现的背后原理,在
理解
原理的基础上我们自己动手实践。 在面试(
多态
是面试题的高频题目)的过程中,能够做到心中自有丘壑。 自己动手模拟
多态
的原理过程中,去如何...
C++对
多态
的
理解
C++对
多态
的学习一、
多态
的
概念
1.1
概念
二、
多态
的定义及实现2.1
多态
的构成条件 一、
多态
的
概念
1.1
概念
多态
的
概念
:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。 举个栗子:比如买票这个行为,当普通人买票时,是全价买票;学生买票时,是半价买票;军人买票时是优先买票。 二、
多态
的定义及实现 2.1
多态
的构成条件 ...
java
多态
的
理解
一、
多态
的定义:
多态
:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。 在运行时,可以通过指向基类的引用,来调用实现派生类(子类)中的方法。 二:
多态
的好处: 使用
多态
,我们可以很好的完成代码的解耦和工作,加强代码的可扩展性,是代码更加灵活,在不改变原有接口方法的情况下简化流程等,总结一下就是: 减耦合 增强可以替换性 可扩展性 灵活性等… 三、实现
多态
的三个条件(前提条件,向上转型、向下转型): 1、继承的存在;(继承是
多态
的基础,没有继承就没有
多态
) 2、子类重写父类的方法。(
多态
下会
【
多态
】
多态
的详细介绍,简单易懂
多态
的介绍
多态
的
概念
多态
的定义及实现
多态
构成的条件:虚函数的重写C++11 override和final重载、覆盖(重写)、隐藏(重定义)的对比抽象类⭐
多态
的原理虚函数表
多态
的
概念
多态
的
概念
:简单来讲,
多态
的意思就是多种形态,或者说,去完成某个行为,当不同的对象去完成时会产生出不同的状态 也可以
理解
为我们人去完成同一件事情,但是每一个人去完成,都会产生不一样的结果 这里我们简单的演示一下 class Base { public: virtual void print() { cout <&l
Java中的
多态
如何
理解
——详解
🎈🎈🎈本篇文章我们主要讲解的是Java中的
多态
,那么什么是
多态
呢?同类型的对象,执行同一个行为,会表现出不同的行为特征。接下来让我们一起对
多态
进行详细地讲解。
C++ 语言
64,636
社区成员
250,540
社区内容
发帖
与我相关
我的任务
C++ 语言
C++ 语言相关问题讨论,技术干货分享,前沿动态等
复制链接
扫一扫
分享
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++
技术论坛(原bbs)
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
请不要发布与C++技术无关的贴子
请不要发布与技术无关的招聘、广告的帖子
请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下
试试用AI创作助手写篇文章吧
+ 用AI写文章