C++和面向对象的一点看法,欢迎讨论 (谈多态 1)

Last_Dodo 2002-01-30 07:52:40
近来参与dynamic_pump的“C++的多态与重载好象作用差不多,谁能讲讲啊?”(hppt://www.csdn.net/Expert/topic/488/488294.shtm)的讨论,觉得很有意思。于是,想把这问题括充一下与各位共同学习。

我常碰到“怎样来衡量C++代码是否面向对象(OO)或在面向对象方面做得好不好?”这样一个问题。我觉得这是个很不好回答的问题,而且回答好这个问题对我本身对OO的认识很有帮助。

我认为,面向对象(OO)至少包含以下几方面(有些中文翻译我不知道,请原谅):
1。Abstraction;
2。Encapsulation;
3。Inheritance(继承);
4。Polymorphism(多态)。
这里最不直观的是多态,所以先对它和大家一起来探讨一下。

Polymorphism是希腊词,意为“many forms”或“many types”。显然它的意思不够清楚。我找来我所有关于OO的书(大约十来本,有讲语言的,OOA/OOD的,OO modeling的,面向对象的软件工程OOSE的,还有design patten设计模式等),比较了一下各位作者的看法。总的说来看大致分为三类:广义的多态,狭义的多态,和较普遍接受的多态。

广义的多态包括重载和覆盖,它可以是早捆绑(static binding)或晚捆绑(dynamic binding or run-time binding)。我只在Grady Booch的<<Object-Oriented Analysis and Design>>见到这样的说法。

狭义的多态只包括晚捆绑的覆盖,我只在“四人帮”的<<设计模式>>上见到。

较普遍的看法是(Ivar Jacobson的):"Polymorphism means that the sender of a stimulus does not need to know the receiving instance's class. The receiving instance can belong to an arbitraty class". 显然它包含早捆绑和晚捆绑。比如在下面的C++代码中就用到它们:
class Shape
{
public:
Shape(const char *shapeName);
virtual ~Fruit();

const char *name() const { return _name; }
virtual void draw(Window &wd) const ;
...
private:
...
char *_name;
};

void drawShape(const Shape &shape)
{
Window window(...);
...
window.printText(shape.name()); //polymorphism with 早捆绑.
shape.draw(window); //polymorphism with 晚捆绑.
...
}

先说这么多,希望听听大家的意见。
...全文
346 27 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
Last_Dodo 2002-02-06
  • 打赏
  • 举报
回复
谢谢cber(cber)给出到Rebert Martin文章的link.

Robert Martin在cber(cber)列出的一文中的谈到的多态包括下面的C程序:
...
char c = getchar();
...
在链入不同的库时(getchar()可能定义成不同的程序行为,如从键盘上读一字符或从磁盘中读一字符等)的多态体现。
我个人觉得他谈的DIP是OO中abstraction的一个原则。当然其中一段提到类似上面的C程序来实现多态,对了解“polymorphism without virtual function"很有帮助。

Stonechina:你说:“通过编译器的逆向引用实现多态”在现行的平台上多不实现。可否给大家多点说明?先谢谢了!

认为晚捆绑才是多态的各位能否说明一下为什么?谢谢!
xuanyun 2002-02-06
  • 打赏
  • 举报
回复
昨天看《Java语言入门》,里面说由于子类型与父类型有“is a”的关系,因此子类型可以在父类型使用的地方使用,这就是所谓的“子类型多态性(subtype polymorphism)”。
dgzdx 2002-02-06
  • 打赏
  • 举报
回复
关注!
tenderfoot 2002-02-05
  • 打赏
  • 举报
回复
太精彩了
stonechina 2002-02-04
  • 打赏
  • 举报
回复

"通过编译器的逆向引用实现多态"在现行的平台上多不实现,
即先行windows&unix下的编译器都不是这样工作的:

WIN32 VC6.0
SUNOS WorkShop Compilers 5.0 C++ 5.0
OSF1V5.0(DEC) Compaq C++ V6.2-024
AIX4.3.2(IBM) C++ Professional / C for AIX Compiler, Version 5
HPUX B.11 HP ANSI C++ B3910B A.03.25
gcc version 2.95.2


cber 2002-02-04
  • 打赏
  • 举报
回复
"Polymorphism without virtual function"的另一种方法是直接基于Library之上的函数调用,最典型的就是IOStream,在Robert Martin的Engineering Notebook的第3篇讲述DIP(the Dependency Inversion Principle)的文章中我们可以看到具体的示例(http://www.objectmentor.com,其中文翻译见C++ View第4期的“依赖倒置原则DIP”)
hezh 2002-02-04
  • 打赏
  • 举报
回复
对于方法的执行,分为早期捆绑与晚期捆绑。多态属于晚期捆绑。实在执行期才确定调用,对于有虚函数的类,无论基类或者继承类,都有一个vtable。在运行时vptr确定对象的型别,指向相应的多态函数!
Last_Dodo 2002-02-04
  • 打赏
  • 举报
回复
"Polymorphism without virtual function"是基于
对象.函数
调用中,如果对象可以是不同的类型就是"polymorphism"。下面是C++中的例子:
class Base
{
public:
...
void foo();
...
};

class Drived1:public Base {...};
class Drived2:public Base {...};

void OtherApplication::foo(Base &baseObject)
{
...
baseObject.foo();
...
}

在OtherApplication中,你不需要知道baseObject是什么类的。它可以是Base, Derived1, Derived2,以及任何从Base类继承下来的类的对象。我觉得这体现多态中的“many types”即多种形态的多种对象。如果用virtual function,这function的实现可以是多种形态的,它更能体现多态中的“many forms”(因为它包含了对象的多态性,所以它也体现了多态中的“mang types”)。
panjet 2002-02-01
  • 打赏
  • 举报
回复

能不能具体讲一讲“Polymorphism without virtual function”。

Last_Dodo 2002-01-31
  • 打赏
  • 举报
回复
谢谢大家的意见。

谢谢kingofark的推荐,我马上到amazon去把那本书买来看看。

C++鼻祖B.S.对多态在他的两本书中有几段话值得一读:
<<THE C++ PROGRAMMING LANGUAGE>>中13.6.1写道:
A template parameterizes the definition of a type or a function with another type. Code implementing the template is identical for all parameter types, as is most code using the template. An abstract class defines an interface. Much code for different implementations of the abstract class can be shared in class hierarchies, and most code using the abstract class doesn't depend on its implementation. From a design perspective, the two approaches are so close that they deserve a common name. Since both allow an algorithm to be expressed once and applied to a variety of types, people sometimes refer to both as POLYMORPHIC. To distinguish them, what virtual functions provide is called RUN-TIME POLYMORPHISM, and what templates offer is called COMPILE-TIME POLYMORPHISM or PRARMETRIC POLYMORPHISM.
同一本书7.7节,第158页写到:
Pointers to functions can be used to provide a simple form of polymorphic routines, that is, ROUTINES THAT CAN BE APPLIED TO OBJECTS OF MANY DIFFERENT TYPES.
还有些地方提到多态,我就不全抄录了。
在<<The Design and Evolution of C++>>2.9.1节里他谈了“Polymorphism without virtual function”。

在多态这一议题上主要的分歧是重载是不是多态。当然早捆绑是否多态也有些争论。

多数人都同意在下面形式的对象函数调用中:
对象.函数
如果函数名不变而对象可以属于不同的类,它就是多态。当然以“四人帮”为首的一些人(好象回到了从前)不同意。他们要加上一个条件:被调的函数一定要晚捆绑。“四人帮”在<<设计模式>>里是这样定义多态度:
P361:
Polymorphism The ability to substitute objects of matching interface for one another at run-time.
所以我不能苟同,因为要求同名可以理解,要求晚捆绑就似乎有些强词了。

又有些人(多态的鼻祖,Strachey,他主要以“+”做争论点)说:
对象.函数(参数)
调用中只要函数名不变,对象和参数都可变也是多态(这是重载,广义的多态包括它)。我原来较认同现已有所转变。

除了弄清楚什么是多态外,还有更重要的一点。那就是多态有什么好处?它如何帮助我们做好项目/产品。因为无论它如何好,如最终不能体现在日常的工作中,它仍就只能在学术研究中。
GuanXP 2002-01-30
  • 打赏
  • 举报
回复
xuanyun的话很有高度,解渴!!!
xuanyun 2002-01-30
  • 打赏
  • 举报
回复
To:cococut
B.S.的原话应该在《The C++ Programming Language,se》讲模板的那一章。
由于现在书不在手边,因此记不确切,sorry。
Last_Dodo 2002-01-30
  • 打赏
  • 举报
回复
I am at home (night) with my computer just converted to XP and have no chinese input software install. So, please excuse me using English.

Thank you all for your thought. I will response to your posts tomorrow. Hope to see more.

BTW, kids are screaming for my attension ^_^. I'd better go now. Again, thank you all!
eagle_canfly 2002-01-30
  • 打赏
  • 举报
回复
I feel that we should analyze polymorphism through OOA and OOD as a kind of method.
ooKid 2002-01-30
  • 打赏
  • 举报
回复
我说的是eion(电离子)
panjet 2002-01-30
  • 打赏
  • 举报
回复

是不是可以这么认为:只有虚函数的重载才是多态呢?

ooKid 2002-01-30
  • 打赏
  • 举报
回复
我对你的景仰有如滔滔江水,延绵不绝,又犹如黄河泛滥,一发不可收拾
eion 2002-01-30
  • 打赏
  • 举报
回复
Class Animal
{
public:
Animal(){}
~Animal(){}

virtual void poar()=0;
};

class Tiger : public Animal
{
public:
virtual void poar(){cout<<" A Tiger is POAR: AOOOOOOOOOOOOOOO...."<<endl;}
};
class Dog : public Animal
{
public:
virtual void poar(){cout<<" A DOG is POAR: WangWangWang......."<<endl;}
};
class Pig : public Animal
{
public :
virtual void poar() {cout<<" A PIG is POARING: HengHengHeng......."<<endl;]
};
。。。。。。。。。。。。
这时你已经有了很多Animal了,于是你定义了你的宠物数组指针:
Animal *pMyAnimals[100];
当然你还没有100只宠物,只不过你先预留这么多空间来供以后不时之需,现在已经有了三种动物,于是你定义
int nAnimalNum = 3;
pMyAnimals[0] = new Tiger;
pMyAnimals[1] = new Dog;
pMyAnimals[2] = new Pig;
现在你想听听他们的咆哮声,于是:
for(int i=0;i<nAnimalNum;i++) pMyAnimals[i]->poar();
你得到
A Tiger is POARING: AOOOOOOOOOOOOOo.................
A DOG is POARING: WangWangWang................
A PIG is POARING: HengHengHeng...............
不同吧?

现在,你今天发烧了,去买了一只雅虎【Yahoo】,于是,你又定义了一只宠物:
class Yahoo : public Animal
{
public:
virtual void poar() {cout<<" A Yahoo is POARING: Yahoo Yahoo Yahoo ...."<<endl;}
};

并在你的动物园内添加
pMyAnimals[nAnimalNum++]= new Yahoo;
让后听听他们美妙的叫唤声:
for(int i=0;i<nAnimalNum;i++) pMyAnimals[i]->poar();
你得到
A Tiger is POARING: AOOOOOOOOOOOOOo.................
A DOG is POARING: WangWangWang................
A PIG is POARING: HengHengHeng...............
A Yahoo is POARING: Yahoo Yahoo Yahoo..........

好听吧?

这就是多态的一个最有用的例子~~~~~~~~~~~~~~~~~~~~~~~~~


cococut 2002-01-30
  • 打赏
  • 举报
回复
to xuanyun(xuanyun):
不好意思,C++的大教主B.S.认为多态分两种:编译期的多态和运行时多态
不知道你是在那看的,可否告知!我想去参考一下!
warrior 2002-01-30
  • 打赏
  • 举报
回复
大教主言之有理,不过有一种观点认为模板是GP的范畴,而不是OO,这么说GP中也应该有多态的概念了。
加载更多回复(7)

65,184

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧