- 浏览: 3446247 次
- 性别:
- 来自: 苏州
文章分类
最新评论
-
sonichy:
Qt5改动很多,要改改了。
基于QItemDelegate的例子1 SpinBoxDelegate -
我的主页6:
楼主,2.2子查询的分页方式:SELECT * FROM ar ...
Mysql 分页语句Limit用法 -
liguoqi:
非常感谢楼主的用心指导,工具以及图片例子都提供了 赞!
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载 -
liguoqi:
问下这个图片怎么解压损坏呀
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载 -
liguoqi:
楼主讲解的非常详细,还附带工具和图片例子,非常感谢
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载
网上的例子,稍微有点错误。我给更改一下,附件上有源码!如有错误,请指正。
总结一下C++实现接口的技巧。
面向对象的语言诸如JAVA提供了Interface来实现接口,但C++却没有这样一个东西,尽管C++ 通过纯虚基类实现接口,譬如COM的C++实现就是通过纯虚基类实现的(当然MFC的COM实现用了嵌套类),但我们更愿意看到一个诸如 Interface的东西。下面就介绍一种解决办法。
程序6步
1、首先我们需要一些宏:
//******************************************** // Interface.h //主要是宏定义一些关键词,可以形成接口类 //******************************************** #ifndef INTERFACE_H #define INTERFACE_H #define Interface class #define DeclareInterface(name) Interface name { \ public: \ virtual ~name() {} #define DeclareBasedInterface(name, base) class name : \ public base { \ public: \ virtual ~name() {} #define EndInterface }; #define implements public #endif
2、有了这些宏,我们就可以这样定义我们的接口类:
//*********************************************** // IBar.h //通过宏定义生成我们的接口类,写一些纯虚函数 //*********************************************** #ifndef IBAR_H #define IBAR_H #include "Interface.h" DeclareInterface(IBar) virtual int GetBarData() const = 0; virtual void SetBarData(int nData) = 0; EndInterface #endif
3、再写一个父类BasicBar.h
//*********************************************** // BasicBar.h //Bar类的父亲类,用来继承测试 //*********************************************** #ifndef BASICBAR_H #define BASICBAR_H #include <iostream> class BasicBar { public: BasicBar(int x) { } ~BasicBar(){} virtual int getBarData1() const { std::cout <<"Get BasicBar!"; return 0; } virtual void setBarData1(int nData) { } }; #endif
4、现在我们可以像下面这样来实现我们的接口Bar.h了:
//*********************************************** //Bar.h //实现IBar接口的类 //*********************************************** #ifndef Bar_H #define Bar_H #include "Interface.h" #include "BasicBar.h" #include "IBar.h" #include <iostream> class Bar :public BasicBar,implements IBar { public: Bar(int x=0) : BasicBar(x) { } ~Bar(){} virtual int getBarData() const { std::cout <<"Get Bar!"; return 0; } virtual void setBarData(int nData) { } }; #endif
5、 怎么样,很简单吧,并不需要做很多的努力我们就可以在C++中使用接口了。在Main函数中引用我们的接口(我建立的是Qt 终端应用程序 )
//*********************************************** // main.h //主函数 //*********************************************** #include <QtCore/QCoreApplication> #include "IBar.h" #include "DataAccess.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); //IBar *bar = new Bar(); IBar *bar = DataAccess::createBar(); bar->getBarData(); delete bar; return a.exec(); }
另外的问题:C++中不许我们实例化抽象类,如IBar *bar = new IBar();
我们只能通过上述main.cpp中的IBar *bar = new Bar();实现, 这样我们还必须指定实例化那个对象Bar,好像前面的努力都白费了啊!!那怎么办呢,我们需要一个工厂:
6、建立一个数据工厂,DataAccess.h
//*********************************************** // DataAccess.h //数据工厂,通过它调用对象类,返回给接口函数 //*********************************************** #ifndef DATAACCESS_H #define DATAACCESS_H #include "IBar.h" #include "Bar.h" class DataAccess { // Construction & Destruction public: DataAccess() { } ~DataAccess() { } static IBar* createBar() { //返回对象给IBar接口 return(new Bar()); } }; #endif
这个时候,我们把第5步的main.cpp调用接口方法改一下:
//*********************************************** // main.h //主函数 //*********************************************** #include <QtCore/QCoreApplication> #include "IBar.h" #include "DataAccess.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); //IBar *bar = new Bar(); IBar *bar = DataAccess::createBar(); bar->getBarData(); delete bar; return a.exec(); }
整个过程中接口不负责任何具体操作,其他的程序要连接业务类、数据库的话,只需要构造一个业务对象、数据访问对象就OK,而不管工厂类如何变化。这就是接口的意义----抽象。
接口宏定义可以更简单点
上述步骤中我们可以把步骤1和步骤2写的更简单些,我们只需要Interface 和 implements 的宏定义,
这样我们的接口定义类IBar灵活性更强,可以继续继承其他的接口类,也更符合java、C#等语言写接口类的风格。
步骤1:Interface.h
//******************************************** // Interface.h //主要是宏定义一些关键词,可以形成接口类 //******************************************** #ifndef INTERFACE_H #define INTERFACE_H #define Interface class //#define DeclareInterface(name) Interface name { \ //public: \ // virtual ~name() {} // //#define DeclareBasedInterface(name, base) class name : \ //public base { \ //public: \ // virtual ~name() {} // //#define EndInterface }; #define implements public #endif
步骤2:IBar.h
//*********************************************** // IBar.h //通过宏定义生成我们的接口类,写一些纯虚函数 //*********************************************** #ifndef IBAR_H #define IBAR_H #include "Interface.h" Interface IBar { public: virtual ~IBar(){} virtual int getBarData() const = 0; virtual void setBarData(int nData) = 0; }; //DeclareInterface(IBar) // //virtual int getBarData() const = 0; //virtual void setBarData(int nData) = 0; //EndInterface #endif
备注:
然而,由于这种C++实现接口方式并不是语言本身所直接支持的特性,所以我们需要遵循一些规则:
a) 声明一个类的时候,如果你的类除了要从接口类继承外还要从另一个类继承(结构上的继承,即is a关系),则把这个类作为第一个基类,就像我们平时做的一样,譬如CFrameWnd从CWnd继承,CBitmapButton从CButton继承,CMyDialog从CDialong继承。当你要从MFC类派生的时候,这尤其重要,把他们声明为第一个基类以避免破坏MFC的RuntimeClass机制。
b) 其他的基类紧跟其后,有多少就跟多少,如果你需要的话。譬如:class Bar: public BasicBar, implements IBar, implements IOther, implements IWhatever, ...
c) 接口类里面不要声明任何成员变量。接口类仅用于描述行为而不是数据。当你要作多重继承时,这样做可以避免数据成员被从同一个接口类多次继承。
d) 接口类的所有成员函数定义为纯虚函数。这可以确保你的实现类来实现这些函数的全部,当然你也可以在抽象类实现部分函数,只要在你的派生类里实现剩下的函数。
e) 不要从除了接口类的其他任何类派生你的接口类。DeclareBasedInterface()可以做到这个.普通类可以选择实现基接口还是派生的接口,后面一种意味着两者都要实现。
f) 将一个指向实现接口的类的指针赋值给一个指向该接口类的指针是不需要强制类型转换的,但反过来将一个接口类的指针赋值给一个实现该接口的类的指针就需要 一个显式的强制类型转换。事实上我们可能会使用多重继承,这样这些转换我们就不能使用老式的转换。不过使用运行时类型信息(使用/GR选项)和动态类型转 换可以很好的工作当然也更安全。
g) 此外dynamic_cast为你提供了一种查询一个对象或接口是否实现了一个指定的接口的途径。
h) 你还要非常小心的避免不同接口函数的命名冲突。
如果你仔细观察DeclareInterface 和 DeclareBasedInterfaca宏你会发现有一个操作是必须的:每个接口类都有一个虚析构函数。你可能认为这不重要,但是如果没有这个就可能会导致一些问题,看看下面的例子:就像你看到的一样,这里有一个类工厂,它根据BarType来创建一个IBar的实现,当你使用完以后你当然希望要delete该对象,你会像下面这样做:
int main() { IBar* pBar = BarFactory::CreateBar(Bar); pBar->SetName("MyFooBar"); delete pBar; // Oops! }
delete pBar 做了什么取决于该对象是否有一个虚析构函数。如果Bar没有一个虚析构函数,则只有IBar 的隐式的空析构函数被调用,Bar的析构函数不会被调用,这样就发生了内存泄露。接口类里虚析构函数的声明避免了这用状况,它确保每个实现接口的类都有一 个虚析构函数。
当你使用DeclareInterfac的时候,记得使用EndInterface和它匹配。Interface 宏和 implements宏仅仅是代替了class和public,这看起来是多余的,但我认为它们更明确的表达了代码的意图。如果我这么写:class Bar: public IBar,你可能认为这只是一个简单的继承;但如果我这么写:class Bar: implements IBar,你就会看到它实际的价值和意图---这是对一个接口的实现,而不是简单的一次继承。
- TestInterface源码.rar (712.5 KB)
- 下载次数: 91
评论
你看看CSDN上的java与C++接口的区别。
http://bbs.csdn.net/topics/477099
#define Interface class Interface IBase {} class Derive : public IBase {} void main(...) { IBase *ba = new Derive; }
是不是这样定义有什么弊端呢?
兄弟,文章开头已经说明了。这是想向java编程风格靠拢。java里有“接口”这种定义,C++没有。
class Bar :public BasicBar,implements IBar
#define Interface class Interface IBase {} class Derive : public IBase {} void main(...) { IBase *ba = new Derive; }
是不是这样定义有什么弊端呢?
兄弟,文章开头已经说明了。这是想向java编程风格靠拢。java里有“接口”这种定义,C++没有。
class Bar :public BasicBar,implements IBar
#define Interface class Interface IBase {} class Derive : public IBase {} void main(...) { IBase *ba = new Derive; }
是不是这样定义有什么弊端呢?
兄弟,文章开头已经说明了。这是想向java编程风格靠拢。java里有“接口”这种定义,C++没有。
class Bar :public BasicBar,implements IBar
#define Interface class Interface IBase {} class Derive : public IBase {} void main(...) { IBase *ba = new Derive; }
是不是这样定义有什么弊端呢?
兄弟,文章开头已经说明了。这是想向java编程风格靠拢。java里有“接口”这种定义,C++没有。
class Bar :public BasicBar,implements IBar
#define Interface class Interface IBase {} class Derive : public IBase {} void main(...) { IBase *ba = new Derive; }
是不是这样定义有什么弊端呢?
发表评论
-
更换博客地址告示
2012-12-03 18:56 2593更换博客地址告示 ... -
收款主页设计
2012-11-17 11:01 0文档信息 版权声明:自由转载-非商用-非衍生- ... -
10个精选国外免费空间
2012-11-12 16:06 6330最近想申请一个免费空间,发现国内基本没有。。。。唉。 ... -
长光所考博信息
2012-09-24 14:25 2699总结一下,以后有个奔头。。搞科研的收入太微薄了。唉。。。 ... -
The file contains a character that cannot be represented in the current code pag
2012-08-17 10:17 6326vs2008 打开网上下载的Qt项目,结果编译时无法通过,出 ... -
64位操作系统,编译程序出现X86和X64的冲突
2012-08-16 20:10 0问题1:1>QtGuid4.lib(QtGuid4.d ... -
通用日志系统开发【转】
2012-08-06 15:20 42411.前言 中大型软件项 ... -
U盘制作WinPE系统【转】
2012-07-27 11:36 2523不带光驱的笔记本的网友和没有光驱的台式机的网友如何安 ... -
博客文章标题横线框
2012-06-28 11:47 0分析 ... -
触摸屏介绍
2012-05-30 16:03 1980有一个项目,需要购买一台触摸屏设备。 了解一下触摸屏的基础知 ... -
有谁知道高速大数据量无线传输技术
2012-05-28 11:53 2506有谁知道高速大数据量无线传输技术? 想了解一下无线传输 ... -
自由在博客里插入广告,有钱你不赚吗???
2012-05-25 18:37 01、一直在ITeye里写技 ... -
自由在博客里插入广告,有钱你不赚吗???
2012-05-25 15:22 6633其实这些广告也没啥意 ... -
支持javascript的博客汇总
2012-05-25 09:27 2485写这篇文章的目的主要是为想在公共博客上布置广告的朋友提供一些参 ... -
支持js代码的博客有哪些?
2012-05-25 09:20 32981、支持js代码的博客谷歌博客, 雅虎奇摩,博客大巴,jimd ... -
VS2008无法下断点调试的原因
2012-05-02 11:18 19327VS2008单步调试时出错,原来的断点处显示一个空心圆加 ... -
VS2008无法下断点调试的若干解决办法
2012-05-02 09:19 4040我使用了第一种方法,暂时恢复了断点调试。 调试程 ... -
【转】串口通讯—通信协议
2012-02-29 00:11 2640转:http://cs.nju.edu.cn/y ... -
Ankhsvn 改名出错
2012-02-16 18:32 3174总结只改变文件名字大小写的最终解决方法。 这种只需要改 ... -
visio2010 用键盘上的上下键为什么移动不了选中的部分,而是整个画布都在移动?
2011-12-23 14:56 10618visio2010画的流程图,选中框图后,用键盘上的上下键为什 ...
相关推荐
总结,C++库封装JNI接口实现Java调用C++涉及的主要步骤包括:声明Java中的本地方法,生成JNI头文件,编写C++实现,编译成库,最后在Java中加载并调用。这个过程需要理解Java和C++之间的数据类型转换,以及如何在两种...
### Creo二次开发 C++接口开发使用说明书 #### 一、引言 在现代工业设计与制造领域,Creo作为一款先进的三维CAD软件,被广泛应用于产品设计与工程分析之中。随着技术的发展与用户需求的增长,对Creo进行二次开发的...
总结一下,实现"C++实现Https Server支持restful json"涉及到以下步骤: 1. 引入如Poco这样的第三方库以支持HTTPS和HTTP处理。 2. 创建SSL上下文,加载服务器证书和私钥。 3. 设置服务器套接字并开始监听HTTPS连接...
JNA通过定义Java接口来映射C/C++函数,并在运行时动态加载本地库,实现调用。这极大地简化了Java代码与C/C++代码之间的交互过程。 要将C++头文件转换为JNA接口,我们通常会使用一个名为SWIG(Simplified Wrapper ...
总结来说,C++中的接口主要通过抽象基类和纯虚函数实现,提供了模块间的解耦和多态性。通过接口,我们可以在不关心具体实现的情况下调用功能,这在大型项目或跨模块通信中尤为重要。在实际编程中,接口的设计和使用...
总结起来,C++实现文件传输功能涉及的关键知识点包括: 1. 使用`fstream`库进行文件的读写操作。 2. 套接字编程,包括创建、绑定、监听、接受连接以及发送和接收数据。 3. 可能的多线程编程,利用`<thread>`库实现...
总结,基于 C++ 的 gRPC 服务端 demo 主要涉及以下步骤:定义服务和消息类型、生成服务接口和消息类、实现服务逻辑、启动 gRPC 服务器以及编写客户端进行测试。gRPC 结合 C++ 的强大功能,提供了高效、可靠的分布式...
Wind C++接口是上海万得信息技术股份有限公司(Wind资讯)提供给编程用户的一套C++编程接口,允许用户通过C++语言编写程序来访问和操作Wind股票软件中的数据,从而实现各类数据的查询以及交易功能。这些接口被广泛...
### C++调用HTTP实现方式详解 #### 一、引言 在现代软件开发中,HTTP(HyperText Transfer Protocol)协议被广泛应用于客户端与服务器之间的通信。C++作为一种强大的编程语言,同样支持对HTTP协议的操作。本文将...
总结来说,实现基于C++的简易AES加解密算法涉及密码学理论、C++编程技巧和数据安全实践。在具体实现过程中,需要理解和掌握AES的内部工作原理,以及如何在C++中有效地表示和操作数据,以确保算法的正确性和效率。...
### 线程池原理及创建(C++实现) #### 一、线程池的重要性 在现代计算环境中,网络服务器面临着处理大量并发请求的挑战,其中包括但不限于Web服务器、电子邮件服务器和数据库服务器。这类服务器通常需要在短时间...
《3DES C++接口开发详解》 3DES(Triple Data Encryption ...总结来说,3DES C++接口的开发涉及密钥管理、子密钥生成、加密解密过程以及性能监控。通过理解这些关键点,开发者可以构建一个安全且高效的文件加密系统。
总结下C++中模块(Dll)对外暴露接口的方式: (1)导出API函数的方式 (2)导出类方式 (3)COM方式
总结,通过`AlipayOpenapiCpp-master`项目,开发者可以学习到如何在C++环境中集成支付宝接口,实现支付功能,并利用回调URL来获取并处理支付结果。这不仅对C++开发者具有指导意义,对于理解支付系统的架构和流程也...
桥接模式是一种设计...在C++中,我们可以利用类的继承和接口来实现这一模式,从而提高代码的可扩展性和可维护性。在实际项目中,尤其是在需要处理多个抽象层次和实现方式的情况下,桥接模式是一个非常有价值的工具。
在提供的C++源码中,你将找到实现了AES加密的类或函数,可能包括`AES_ECB_Encrypt`、`AES_CBC_Encrypt`等接口。使用这些API时,你需要提供密钥、明文数据、以及在CBC模式下所需的初始化向量。例如: ```cpp #...
总结起来,虽然C语言不具备C++那样的内置多态机制,但通过函数指针和结构体,我们可以实现类似的功能。这种方法需要更高的编程技巧和更严谨的设计,但在某些场合下,如嵌入式系统或性能要求极高的场景,可能是一种...