<C++> 类的‘’实现‘’与‘’接口‘’分离
来源:互联网 发布:js 判断event 编辑:程序博客网 时间:2024/04/25 09:56
C++这门语言囊括了多种语言范式,并不是严格的
OOP
语言,所以在“实现与接口的分离”这一方面做得并不算好。 这里简述C++
的类设计中把实现与接口分离的方法.
在C++的某个class
的定义中,不仅声明了接口,还可以看到实现的具体细节,当然这个视角是针对类内部的,通常是在私有域private
中,比如下面这个类:
class Person {public:Person(const std::string& name, cpnst Date& birthday,const Address& addr);std::string name() const;std::string birthDate() const;std::string address() const;private://实现的细节std::string theName;Date theB工rthDate;Address theAddress;};
要实现这么一个类,一般的做法就是在所在声明的头文件中include
Date和Address两个类的声明文件include"date.h"/include"address.h"
,如果Date或者Address类发生了改动,那么连带Person类及包含Person头文件的后续文件都要重新编译。这样子的话Person类的使用者就会有极大的不便,Person/Date/Address中的任何一个类改动,Person客户端都必须重新编译。
我们可以借鉴类似Java中的做法,声明一个类时,出现的是一个指向该类型的指针,只要分配给该指针足够的空间,我们就可以隐藏其“实现”了。我打一个可能不是那么形象的例子,原始版本就是一本书,我们是这本书的使用者,书中的内容有改动时,出版社就需要重新印刷一份,现在我们不用拿着书了,我们手中只有一个目录,我们需要资料的时候直接按照目录向出版社拿内容,出版社可以随时更新他手头的资料内容,而我们只要专注于“索要”资料就行了。
但是这样子分离的还不够彻底,我们把Person
类分离为两部分,纯粹的两部分,一部分叫实现类(定义为PersonImpl [Person Implementation]),另一部分叫接口类(即 Person)。
把具体的实现放在PersonImpl
类中,然后通过Person
类管理指针形式的PersonImpl
对象,然后把接口暴露给客户,实现分离。
#include <string>#include <memory>class Personlmpl; //实现类的声明class Date; //接口中需要用到的其他类的声明class Address;class Person {public:Person(const std::string& name, const Date& birthday,const Address& addr);std::string name() const;std::string birthDate() const;std::string address() const;private:std::shared_ptr<PersonImpl> plmpl; //指针的形式,且遵循以类管理资源的原则};
在PersonImpl类和Person类中,有着同名的成员函数,接口也是完全一样的
这样的设计,Person类的使用者就完全的与Person/Date/Address三种类的实现细节分离开了,只要专注于接口的使用就OK了。
并且在这样的设计下,如果Date,Address之类的Class有变动,Person类的使用者也不需要重新编译。
另一种方法也许更常见,就是把接口(Interface)
都在一个接口类(抽象类)中描述,然后由它的派生类来具体实现,有着纯虚函数的类就是抽象类,抽象类是一种不能实例化的特殊类,所以经常可以用来描述接口:
class Person {public:virtual -Person();virtual std::string name() const = 0; // =0后缀,即为纯虚函数virtual std::string birthDate() canst = 0;virtual std::string address() const = 0;};
正常的使用就是在派生类中具体实现:
class RealPerson: public Person {public:RealPerson(const std::string& name, const Date& birthday,const Address& addr)theName(name) , theBirthDate(birthday) , theAddress(addr){}virtual -RealPerson() { )std::string name() const;std::string birthDate() const;std::string address() const;private:std::string theName;Date theBirthDate;Address theAddress;}
除此之外,抽象类也是“工厂设计模式”
的一种比较优良的实践,我们可以通过一个在抽象类中定义一个create函数
(通常是静态方法,用static
关键字来修饰),用来动态生成继承体系中的各种实例,都可以通过一个create函数
来实现,当然别忘了,为了满足多态的要求,返回的应该是一个指针(*)或引用(&)。
class Person {public:static std::shared_ptr<Person> create(const std::string& name, const Date& birthday, const Address& addr){return std::shared_ptr<Person>(new RealPerson(name, birthday,addr); //此例中只展示了生成RealPerson实例,更真实的实践中通常取决于参数,环境等等}};
当然两种方法都是很好很实用的剥离“实现”与“接口”的实践,减少类与类之间的耦合度。
他们分别叫做handle class
和interface class
,可以从名字形象的推测出它们的含义。
- <C++> 类的‘’实现‘’与‘’接口‘’分离
- 类的接口与实现的分离
- 代理类:接口与实现的分离
- 类的接口与实现分离的技术
- 类的接口与实现分离的技术
- c++接口与实现的分离
- C++——接口与实现分离技术
- 『C/C++』一个用C/C++分别实现接口与实现相分离的设计原则的例子
- C++接口与实现分离
- C++接口与实现分离
- c++:成员对象,基类初始化列表 接口与实现分离
- [C++]模板类的声明与实现分离问题
- Objective-C类-Objective-C 分离 接口和实现文件
- 第一个所谓的c++接口与实现的分离
- C++中接口与实现分离的技术
- C++中接口与实现分离的技术
- 再论C++中接口与实现分离的技术
- 体验C++中接口与实现分离的技术
- 将二维数组用foreach遍历并以表格的形式输出
- LeetCode (1)
- 修复官方duilib-MenuWnd无法响应子项事件
- 一天搞懂机器学习PPT笔记-1
- 数据结构之——循环双向链表的实现
- <C++> 类的‘’实现‘’与‘’接口‘’分离
- html和css知识总结
- spring jpa 事物配置
- 男人能成就大事的性格
- Dropout
- 009. Spring Bean依赖关系
- MySQL左连接,右连接,等值连接
- Mac下mysql出现错误:ERROR 1055 (42000)
- 【WPS技能】xlsx表格根据单元格的值改变行背景色