扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
在本页阅读全文(共19页)
在C++中,以类、虚函数等为代表的数据抽象功能一直是C++的核心和难点。我认为C++的抽象应该是指:从我们需要解决的问题出发,在与该问题相关的一组关联对象中提取出主要的或共有的部分――说简单一点,就是用相同的行为来操作不同的对象。
从提出问题到找出与该问题相关的对象,这是一个互动的、反复的过程。在对相关对象的抽象中,随着认识的深入,我们可能会修改最初的目标,而最初目标的修改又可能使一组新的相关对象被加入进来。如:假设现在要设计一个基于广域网的邮件服务器,首先可能需要通过socket对底层协议进行封装,为高层的pop3、smtp协议提供一组标准的接口。开始为了使问题简化我们可能计划只封装TCP/IP协议,不过基于以下两点我们有理由修改最初的需求:
1、 pop3、smtp需要的底层接口很简单。除了连接,仅需要发送、接收一块数据的功能
2、 用socket进行网络编程,大多数常见协议间的差别很小,有许多都仅仅只是初始化和连接不同而已我们只需要做很小的努力就可以兼容大多数常用协议(如:ATM、Ipx、红外线协议等)。
现在决定修改需求,除了TCP/IP协议,还要支持一些其他的的常用协议。通过对最初目标的修改,除了TCP/IP协议对象,又会有一组相关的协议对象被加入进来。我们可以很容易从这组相关对象中提出共有的部分,将他抽象到另一个公共对象中。当然,根据具体应用环境不同,这可能并不是最佳方案。
C++中常规的抽象是在一组相互间有“血缘”关系的类中展开的。如:
Class Parent
{
virtual ~Parent(){};
virtual void GetValue(){ .... };
virtual void Test(){ ... };
};
class child1 : public parent
{
virtual ~child1(){};
virtual void GetValue(){...};
virtual void Test(){ ... } const;
};
class child2 : public parent
{
virtual ~child2(){};
virtual void GetValue(){...};
virtual void Test(){ ... } ;
};
(顺便说一句,child1::Test() const 不是基类 parent::Test() 的重载。)
由上可总结出C++中抽象的一些基本特点:
1、被抽象对象必须直接或间接派生至某个类对象
2、如果你不用没有类型安全的操作,如:向下转型操作或强制类型转化操作(像COM那样)。那么派生类中需要抽象的动作必须在某个基类中出现。
3、 基类的析构函数必须是一个虚函数
上述特点一般而言不会影响我们的抽象,但在一些特殊情况下就很难说了。比如:
假设为某个项目进行二次开发,到手的资料可能就是一堆dll、一堆头文件和一堆文档。这些dll里输出了很多的类,其中有一大堆都是离散的、毫无关系的类对象。经过一段时间的开发,你可能发现为了分别操作这些对象,程序中充满了switch...case.../if....else....语句。更扰人的是其实这些对象完全可以从某个基类派生,有些操作完全可以定义成virtual function。但在不能修改source code 的情况下(其实就算有源代码这样的修改也不可行)如何对这组对象进行抽象呢?
还有一些例子,比如:在MFC中,假设我们从Cdialog派生一组对话框类,如果我们在某个派生类中定义了一个自己的virtual function。那么除了重新在Cdialog和派生类之间再派生一个类层次,我们无法从外部以抽象的方式直接调用这个虚函数。但为了一个派生类和一个virtual function就添加一个类层次,这也太.....
将以上特例总结一下:C++中进行抽象的一组类之间必须有“血缘”关系。但在实际应用中我们有
时候有必要对一组离散的、没有关系的类对象(如来自不同的类库或者根本就没有virtual function)进行一些抽象操作――可能因为工作关系,我接触这种情况的机会比较多。传统的C++没有直接提供这方面的支持。在实际应用中我经常使用如下方法:
#include <list>
class parent
{
public:
virtual ~parent(){};
virtual void DoSomething( void ) const = 0;
};
template< typename T >
class child : public parent
{
public:
virtual ~child()
{
delete tu;
}
child( ):
{
tu = new T;
}
void DoSomething( void ) const
{
tu->InitObj();
}
private:
T *tu;
};
class test
{
public:
void InitObj( void )
{
::MessageBox( NULL, "Test", "test...ok!", MB_OK );
}
};
int main()
{
using namespace std;
list< parent* > plist;
parent *par = new child<test>();
plist.push_back( par );
}
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者