这是实现支持继承的pimpl的有效方法吗?
Would this be a valid way to implement pimpl that supports inheritance?
#include <iostream>
#include <memory>
#include <cstdlib>
class IBase
{
public:
IBase() = default;
virtual ~IBase() = default;
virtual void f1() = 0;
};
class IDerived
{
public:
IDerived() = default;
virtual ~IDerived() = default;
virtual void f2() = 0;
};
class BaseImpl : public IBase
{
public:
BaseImpl() = default;
virtual ~BaseImpl() override = default;
virtual void f1() override { /* serious code */}
};
class DerivedImpl : public BaseImpl, public IDerived
{
public:
DerivedImpl() = default;
virtual ~DerivedImpl() override = default;
virtual void f2() override { /* serious code */}
};
class Base : public IBase
{
public:
Base() : m_impl(std::make_shared<BaseImpl>()) {}
virtual ~Base() override = default;
virtual void f1() override { m_impl->f1(); }
protected:
Base(const std::shared_ptr<BaseImpl>& impl) : m_impl(impl) {}
std::shared_ptr<BaseImpl> m_impl;
};
class Derived : public Base, public IDerived
{
public:
Derived() : Base(std::make_shared<DerivedImpl>()) {}
virtual ~Derived() override = default;
virtual void f2() override { impl()->f2(); }
private:
std::shared_ptr<DerivedImpl> impl() { return std::dynamic_pointer_cast<DerivedImpl>(m_impl); }
};
int main()
{
Base base;
base.f1();
Derived derived;
derived.f1();
derived.f2();
std::cin.sync();
std::cin.get();
return EXIT_SUCCESS;
}
它是有效的,但是它看起来太奇怪了,我可能会放弃粉刺
想象一下这样定义Base:
class Base {
public:
Base();
virtual ~Base();
virtual void f1();
protected:
class Impl;
Impl *p_impl; // or shared_ptr, or unique_ptr, or whatever you like.
};
注意这里没有定义Base::Impl
。这是PIMPL习惯用法的一个非常重要的部分,因为您可能不得不在Impl类中使用需要#include
的元素-删除您不想包含在头类中的内容。
派生类看起来像这样:
class Derived: public Base {
public:
Derived();
~Derived();
virtual void f1(); // or not, depends
virtual void f2();
protected:
class Impl2;
Impl2 *p_impl2; // note that Derived::Impl2 might inherit from Base::Impl
};
这仍然隐藏了Base::Impl
和Derived::Impl2
中Base
和Derived
的实现细节,同时给您以任何您喜欢的方式(包括继承)实现Derived
的完全自由。
您的Impl
类应该只包含私有变量和方法。
不要把任何需要从子类访问的东西放在那里。在c++中,将Impl
类子类化是错误的,因为这违背了此模式的目的。
相关文章:
- 在C++中初始化向量映射的最有效方法
- 将此布尔值传递给此函数的最有效方法是什么?
- 比较C++变量的最有效方法
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 存储变量的更有效方法是什么?
- 确保套装新鲜度的有效方法
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 映射唯一值和重复值的有效方法.可以访问键或值的位置
- 在C++事务之间存储大量字符数据的有效方法
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 一种将 Dart 中的字节数据转换为 C++ 中的无符号字符*的有效方法?
- 检查两个向量是否并行的最有效方法
- 从浮点数中删除小数部分但保留类型的有效方法
- 传递非泛型函数的最有效方法是什么?
- 按升序打印矢量的所有元素直到它为空而没有重复项的最有效方法是什么?
- 创建字符串数组的有效方法
- 返回一个引用C++中另一个类对象的对象的有效方法
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- 将一种数据类型的向量复制到同一数据类型的结构向量中的有效方法是什么
- 从std::map值中获取密钥的有效方法