假设我有一个 class B
和一个继承自 B
的 class A : public B
。我想暴露A
的方法,它调用了B
中的一些方法。
现在我想在 pimpl 习语中公开这些方法 - 我真的不知道该怎么做:
A
和B
是否都获得单独的实现类B::impl
和A::impl : public B::impl
使得实现相互继承?然后常规类不继承:class A
和class B
?我意识到这是不可能的,因为实现是
私有(private)的
。实现不子类化
B::impl
和A::impl
但暴露的类做class B
和A 类:公共(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/