如何设计C++接口类

2019-10-06  本文已影响0人  crazyhank

基于C++语言开发的库,需要提供给第三方来调用,就必然会涉及到如何设计接口类。一般来说,有两种方法设计接口类,第一种是PIMP方法,即Pointer to Implementation,在接口类成员中包含一个指向实现类的指针,这样可以最大限度的做到接口和实现分离的原则。第二种方法叫Object-Interface方法,它的思想是采用C++的动态功能,实现类继承接口类,功能接口函数定义成虚函数。

PIMP方法

接口类头文件

Person.h文件:

#ifndef PERSON_H
#define PERSON_H
#include <string>

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 <string>

class PersonImpl {
public:
    PersonImpl(std::string& name);
    virtual ~PersonImpl();
    std::string& getName();
private:
    std::string m_name;
};

#endif

PersonImpl.cpp:

#include "PersonImpl.h"

#include <string>

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 <iostream>
#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 <string>

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 <iostream>
#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 <iostream>

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 <iostream>

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;
}
上一篇下一篇

猜你喜欢

热点阅读