于C++语言开发的库,需要提供给第三方来调用,就必然会涉及到如何设计接口类。一般来说,有两种方法设计接口类,第一种是PIMP方法,即Pointer to Implementation,在接口类成员中包含一个指向实现类的指针,这样可以最大限度的做到接口和实现分离的原则。第二种方法叫Object-Interface方法,它的思想是采用C++的动态功能,实现类继承接口类,功能接口函数定义成虚函数。
PIMP方法
接口类头文件
Person.h文件:
#ifndef PERSON_H#define PERSON_H#include class PersonImpl; //实现类的声明,这里不需要暴露实现细节class Person {public: Person(std::string& name); virtual ~Person(); std::string& getName();//要暴露的功能接口private: PersonImpl *m_personImpl;//指向实现类的对象};#endif
接口类的实现文件
Person.cpp:
#include "Person.h"#include "PersonImpl.h"Person::Person(std::string& name){ m_personImpl = new PersonImpl(name);//在接口类的构造函数中生成一个实现类对象}Person::~Person(){ if (m_personImpl) { delete m_personImpl; }}std::string& Person::getName(){ return m_personImpl->getName();//真正调用的是实现类的功能接口}
实现类的代码
PersonImpl.h:
#ifndef PERSON_IMPL_H#define PERSON_IMPL_H#include class PersonImpl {public: PersonImpl(std::string& name); virtual ~PersonImpl(); std::string& getName();private: std::string m_name;};#endif
PersonImpl.cpp:
#include "PersonImpl.h"#include PersonImpl::PersonImpl(std::string& name){ m_name = name;}PersonImpl::~PersonImpl(){}std::string& PersonImpl::getName(){ return m_name;}
我们可以将这些代码编译成一个动态库:
$g++ -fPIC -shared -o libperson.so Person.cpp PersonImpl.cpp
我们可以写一个测试程序,调用刚刚编译好的动态库:
#include #include "./Person.h"using namespace std;int main(){ string name("hank"); Person p(name); cout << "Name: " << p.getName() << endl; return 0;}
Object-Interface方法
一般来说,如果一个接口类对应有若干个实现类,可以采用这种方法。
接口类头文件
Person.h:
#ifndef PERSON_H#define PERSON_H#include class Person {public: Person(); virtual ~Person(); virtual std::string& getName() = 0;//纯虚函数,保证了调用者不会基于接口类进行实例化操作。};enum GENDER {//定义了性别属性,用于区分不同的实现类对象 MALE, FEMALE};Person* createPerson(GENDER gender, std::string& name);//全局函数,用于创建不同的实现类对象。#endif
接口类实现
Person.cpp:
#include #include "Person.h"#include "Male.h"#include "Female.h"Person::Person(){}Person::~Person(){}Person* createPerson(GENDER gender, std::string& name){ Person* p; switch (gender) { case MALE: p = new Male(name); break; case FEMALE: p = new Female(name); break; default: std::cout << "wrong gender!" << std::endl; return NULL; } return p;}
实现类
(1)Male类
Male.h:
#ifndef MALE_H#define MALE_H#include "Person.h"class Male : public Person {public: Male(std::string& name); virtual ~Male(); std::string& getName();private: std::string m_name;};#endif
Male.cpp:
#include "Male.h"#include Male::Male(std::string& name){ m_name = name;}Male::~Male(){}std::string& Male::getName(){ std::cout << "In Male::getName" << std::endl; return m_name;}
(2)Female类
Female.h:
#ifndef FEMALE_H#define FEMALE_H#include "Person.h"class Female : public Person {public: Female(std::string& name); virtual ~Female(); std::string& getName();private: std::string m_name;};#endif
Female.cpp:
#include "Female.h"#include Female::Female(std::string& name){ m_name = name;}Female::~Female(){}std::string& Female::getName(){ std::cout << "In Female::getName" << std::endl; return m_name;}
测试程序
main.cpp:
#include <iostream>
#include "./Person.h"
using namespace std;
int main()
{
string name("hank");
Person *p = createPerson(FEMALE, name);
cout << "Name: " << p->getName() << endl;
return 0;