电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

多态与面向对象(一)


发布日期:2021/4/13
 

不管时光如何流逝应该说每个人对他职业生涯的第一次面试都是记忆犹新不是吗?

经过前两轮的筛选我推开那扇门小心翼翼地坐在Andy面前我应聘的职位是C++程序员坦率的讲我有一些紧张您知道的一个找不到工作的应届大学生生活是如何地充满压力

能告诉我什么是OO吗?Andy一开口就是这样一句

我有预感他将主要考察我在面向对象方面的编程能力我知道C++支持数种不同的程序设计风格包括面向过程的编程风格(Procedural Programming)泛型编程风格(Generic Programming)基于对象的编程风格(Objectbase Programming)和面向对象的编程风格(Objectoriented Programming)可是什么是OO呢?具体概念我还真的不大清楚

分析问题时我们常常会把事物看作一个一个的对象把具有相同特征的对象看作一个类我想他是不是在期待这样的答案呢

那你对OB又作何解释呢?Andy面无表情

对呀所谓OB就是被称作ADT(Abstract Data Template)的程序设计风格我刚刚所说的不也被OB所支持吗?一直以为自己在使用面向对象编程技术谁知道真是惭愧啊

是的应该说OO留给我印象最深的还是继承和多态现在我只能尽量回想我曾参与过的少得可怜的项目以寻求答案

几乎每个人都同意继承和多态是OO概念可是据我所知真正理解这两个概念的却不多时间有限我们就谈谈多态你知道C++以哪些方法支持多态吗?显然他不想在我身上花太多时间

这个问题对于我还是不难回答的例如有以下继承体系

其中rotate是一个虚拟函数C++ 以三种方法支持多态其一经由一组隐含的转化操作如把一个派生类指针转化为一个指向其公有基类类型的指针

shape *ps = new circle();

其二经由虚拟机制

ps>rotate();

其三经由dynamic_cast和typeid运算符

if (circle *pc = dynamic_cast(ps))

多态的主要用途是经由一个共同的接口来影响类型的封装这个接口通常被定义在一个抽象的base class中这个接口是以virtual function机制引发的它可以在执行期根据object的真正类型解析处到底是哪一个函数实体被调用趁热打铁我敢肯定如果还不能趁此机多说几句的话那将是前功尽弃

如果我写下这样的代码又将怎样呢?Andy飞快地在一张纸片上写下

circle p;

shape s(p);

srotate();

以一派生类对象为初值初始化一个基类对象!这是我的第一反应

这会发生所谓的对象切割同时多态不再呈现虽然我敢肯定我所说的话语可我总感觉Andy另有它意

为什么多态不再呈现?他的眼神流露出一丝疑问

因为多态的特性只有在使用pointer或reference时才能发挥我毫不犹豫的回答

好吧请你讲讲曾参与过的设计Andy似乎已经达到目的后来我才知道C++通过class的pointer和reference来支持多态这种程序设计风格就是所谓的OO

我想起曾经参与的一个项目我的主要任务是通过串口来控制一种叫做云台的外设其实就是根据通信协议将客户请求翻译成相应的字符串然后通过串口发送出去看起来很简单是吗?不过为了争取更大的市场我们必须尽可能多的支持不同厂商提供的不同协议并且能够在未来方便地加入当前尚未支持的协议当时的设计就好像这样子

class CPtzHal

{

public:

CPtzHal(CSerial *pSerial CProtocol *pProtocol);

void sendCommand(int command);

private:

CSerial *m_pSerial;

CProtocol *m_pProtocol;

};

成员函数sendCommand的定义如下

void CPtzHal::sendCommand(int command)

{

if(m_pSerial != NULL && m_pProtocol != NULL)

{

m_pSerial>send(m_pProtocol>getCommandString(command));

}

}

您看我们使用CPtzHal 来接受并处理用户的请求CProtocol 就是我们的协议类通过其成员函数getCommandString 得到指定的请求ID所对应的应该发往串口的字串CSerial实际上是串口类而CSerial::send的作用当然是把指定的字串发送出去

那么你是怎么保证方便的添加新协议呢?Andy轻轻移了移身体

如您所知CProtocol理所当然是一个基类而且我把它设计成一个抽象基类所有的具体的协议类都将从它派生我缓缓说道同时写下以下代码

class CProtocol

{

public:

virtual ~CProtocol(){};

virtual string getCommandString(int) = ;

};

您看因为是一个基类其析构函数当然要声明为virtual……

等等既然析构函数什么都不做为什么要给它一个空的函数体?Andy开始试探我

正如我刚才所说我是有义务要声明它们的本来我也不想给出实现可是即使我同意编译器也不会答应啊

不错Andy的首肯令我颇有些难为情

至于每一个具体的协议类都必须实现在CProtocol中声明的那些纯虚函数(pure virtual function)我飞快地写出以下代码

class CIntelProtocol : public CProtocol

{

public:

string getCommandString(int command);

};

string CIntelProtocol::getCommandString(int command)

{

// 返回相应的字串

}

您看CIntelProtocol正是封装了英特尔的协议当有新的协议加进来的时候做法就如同以上一般从CProtocol派生出一个新的协议类

从Andy的表情可以看出他还算满意作为协议类的客户CPtzHal并不需要知道这个具体协议到底是英特尔的还是三星的说不准它是将来某个别的厂商所提供的可是这有什么关系呢?不管这点如何改变CPtzHal压根就不用变正是多态所带来的好处

我和Andy的对话就这样结束了吗?不还没有这正如我要跟你讲的有关OOP的故事还将继续

上一篇:使用AWT 将Graphics对象转换为Image对象

下一篇:JFC/Swing活学活用之定制JList显示