Pimpl习语

时间:2017-03-25 19:39:21

标签: c++ inheritance pimpl-idiom

假设我有一个class B和一个class A : public B,它继承自B。我想公开A的方法,它们在B中调用了一些方法。

现在我想在pimpl成语中公开这些方法 - 我真的不确定如何做到这一点:

  • AB是否都有单独的实现类B::implA::impl : public B::impl,以便实现继承彼此?然后常规类不继承:class Aclass B

    我意识到这是不可能的,因为实现是private

  • 实现不是B::implA::impl的子类,但是公开的类会class Bclass A : public B。但是A::impl中的方法如何在B::impl中调用父方法?

  • 通过参数中的指针 - 参见下面的示例。

由于

修改:以下是一个示例代码段 - 这是正确的吗?

test.hpp

#include <iostream>

class B {
private:
    class impl;
    std::unique_ptr<impl> pimpl;

public:
    B();
    ~B();
    B(B&&) = default; 
    B(const B&) = delete;
    B& operator=(B&&);
    B& operator=(const B&) = delete;

    void my_func() const;
};

class A : public B {
private:
    class impl;
    std::unique_ptr<impl> pimpl;

public:

    A();
    ~A();
    A(A&&) = default; 
    A(const A&) = delete;
    A& operator=(A&&);
    A& operator=(const A&) = delete;

    void access_my_func();
};

TEST.CPP

#include "test.hpp"

// Implementation of B
class B::impl
{
public:
    impl() {};

    void impl_my_func() { 
        std::cout << "impl_my_func" << std::endl;
        return; 
    };
};

// Constructor/Destructor of B
B::B() : pimpl{std::make_unique<impl>()} {};
B::~B() = default;
B& B::operator=(B&&) = default;

// Exposed method of B
void B::my_func() const {
    std::cout << "B::my_func" << std::endl;
    pimpl->impl_my_func();
    return; 
};


// Implementation of A
class A::impl
{
public:
    impl() {};

    void impl_access_my_func(const A& a_in) {
        std::cout << "impl_access_my_func" << std::endl;
        a_in.my_func();
        return;
    };
};

// Constructor/Destructor of A
A::A() : pimpl{std::make_unique<impl>()} {};
A::~A() = default;
A& A::operator=(A&&) = default;

// Exposed method of A
void A::access_my_func() {
    std::cout << "A::access_my_func" << std::endl;
    pimpl->impl_access_my_func(*this);
    return;
};




// Later in the main.cpp file
int main() {

    // Make an object
    A my_A_object;
    my_A_object.access_my_func();

    return 0;
};

1 个答案:

答案 0 :(得分:1)

如果你从B继承A,那么A应该能够调用B类的接口。它不应该依赖它的实现。

Pimpl-Ideom只是一种处理C ++限制的方法,你无法拆分类的私有,受保护和公共部分的声明。由于您不希望将类的私有部分暴露给类用户,并且不希望将受保护的部分公开给不想要子类的用户,因此Pimpl-Ideom会将这些部分从头文件移开。

回答你的问题:

  • A类必须是B的子类,这就是OOP的意思。
  • class A :: impl不需要依赖B :: impl来完成它的工作。
  • 如果你想走极端,你可以设想一个B :: protected_impl,A :: impl可以是子类。为此,您必须使用protected_impl声明创建一个单独的标头,以便A :: impl可以使用它。