Pimpl 习语中的 C++ 继承

标签 c++ inheritance pimpl-idiom

假设我有一个 class B 和一个继承自 Bclass A : public B。我想暴露A的方法,它调用了B中的一些方法。

现在我想在 pimpl 习语中公开这些方法 - 我真的不知道该怎么做:

  • AB 是否都获得单独的实现类 B::implA::impl : public B::impl 使得实现相互继承?然后常规类不继承:class Aclass B?

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

  • 实现不子类化 B::implA::impl 但暴露的类做 class BA 类:公共(public) B。但是 A::impl 中的方法如何调用 B::impl 中父级的方法呢?

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

谢谢

编辑:这是一个示例代码片段 - 这是否正确?

测试.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();
};

测试.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;
};

最佳答案

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

Pimpl-Ideom 只是一种处理 C++ 局限性的方法,即您不能拆分类的私有(private)部分、 protected 部分和公共(public)部分的声明。由于您不想将类的私有(private)部分暴露给类用户,并且不想将 protected 部分暴露给不想子类化的用户,因此 Pimpl-Ideom 将这些部分从头文件中移除。

回答你的问题:

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

关于Pimpl 习语中的 C++ 继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43021079/

相关文章:

c++ - 如何在不暴露内部结构的情况下与 Pimpl 交换私有(private)数据?

c++ - 带有模板成员函数的 Pimpl Idiom

c++ - 继承与纯虚函数混在一起,有什么方法可以不必重新定义它们呢?

c++ - 使用整数运算的平滑算法

c# - 一个类是否可能只继承一些(不是全部)基类成员?

python - 在两个相关类中使用继承的最佳方式是什么

c++ - 一次生成 1000 个随机卡片组洗牌 C++

C++取消引用并将值分配给指针的正确方法

C# : Building java-style enums with inheritance

c++ - pimpl 中的方法是否内联?