在C+中,除了内部API之外,还提供外部受保护的API和类层次结构+; 我正在研究C++库,其中有一个抽象类的集合,一些开发人员使用库,根据它们的需要,需要子类与库的其余部分进行交互。这被认为是必要的,因为库本身需要能够在内部实例化和使用这些类(有点像插件系统)。这些类有一个受保护的API,用于与库的其余部分交互。它们还需要一个单独的内部接口来管理实例,方法是提供指向内部结构的指针,并调用对最终派生类透明的其他管理函数

在C+中,除了内部API之外,还提供外部受保护的API和类层次结构+; 我正在研究C++库,其中有一个抽象类的集合,一些开发人员使用库,根据它们的需要,需要子类与库的其余部分进行交互。这被认为是必要的,因为库本身需要能够在内部实例化和使用这些类(有点像插件系统)。这些类有一个受保护的API,用于与库的其余部分交互。它们还需要一个单独的内部接口来管理实例,方法是提供指向内部结构的指针,并调用对最终派生类透明的其他管理函数,c++,c++14,C++,C++14,当前的解决方案涉及为每个公共类的管理接口创建一个内部基类,当需要执行管理功能时,内部库功能仅强制转换到该类 以下是一个简化的示例: class BaseInternal { public: void doSomething(); }; class BaseComponent { public: BaseComponent(); virtual ~BaseComponent(); void manageComponent(); void setInternal(std::sh

当前的解决方案涉及为每个公共类的管理接口创建一个内部基类,当需要执行管理功能时,内部库功能仅强制转换到该类

以下是一个简化的示例:

class BaseInternal
{
public:
  void doSomething();
};

class BaseComponent
{
public:
  BaseComponent();
  virtual ~BaseComponent();
  void manageComponent();
  void setInternal(std::shared_ptr<BaseInternal>);
protected:
  const std::shared_ptr<const BaseInternal> getInternal() const;
  const std::shared_ptr<BaseInternal> getModInternal();
private:
  std::shared_ptr<BaseInternal> internal;
};

class Base : public BaseComponent
{
public:
  Base();
  virtual ~Base();
protected:
  // library "plugin" API
  virtual void overrideMe() = 0;
  virtual void overrideMe2() = 0;
  void foo() { getModInternal()->doSomething(); }
private:
  // Component access hidden here
  using BaseComponent::manageComponent;
  using BaseComponent::setInternal;
  using BaseComponent::getInternal;
  using BaseComponent::getModInternal;
};

class AInternal
{
public:
  void doASomething();
};

class AComponent
{
public:
  AComponent();
  virtual ~AComponent();
  void manageA();
  void setAInternal(std::shared_ptr<AInternal>);
protected:
  const std::shared_ptr<const AInternal> getAInternal() const;
  const std::shared_ptr<AInternal> getModAInternal();
private:
  std::shared_ptr<AInternal> aInternal;
};

class A : public AComponent, virtual public Base
{
public:
  A();
  virtual ~A();
protected:
  // library "plugin" API for A
  void bar() { getModAInternal()->doASomething(); BaseComponent::getModInternal()->doSomething();}
private:
  // Component access hidden here
  using AComponent::manageA;
  using AComponent::setAInternal;
  using AComponent::getAInternal;
  using AComponent::getModAInternal;
};

class BInternal
{
public:
  void doBSomething();
};

class BComponent
{
public:
  BComponent();
  virtual ~BComponent();
  void manageB();
  void setBInternal(std::shared_ptr<BInternal>);
protected:
  const std::shared_ptr<const BInternal> getBInternal() const;
  const std::shared_ptr<BInternal> getModBInternal();
private:
  std::shared_ptr<BInternal> bInternal;
};

// Base
class B : public BComponent, virtual public Base
{
public:
  B();
  virtual ~B();
protected:
  // library "plugin" API for B
  void baz() { getModBInternal()->doBSomething(); BaseComponent::getModInternal()->doSomething();}
private:
  // Component access hidden here
  using BComponent::manageB;
  using BComponent::setBInternal;
  using BComponent::getBInternal;
  using BComponent::getModBInternal;
};

class CInternal
{
public:
  void doCSomething();
};

class CComponent
{
public:
  CComponent();
  virtual ~CComponent();
  void manageC();
  void setCInternal(std::shared_ptr<CInternal>);
protected:
  const std::shared_ptr<const CInternal> getCInternal() const;
  const std::shared_ptr<CInternal> getModCInternal();
private:
  std::shared_ptr<CInternal> bInternal;
};

// Derived virtually from A and B since there may be future classes
// derived from C
class C : public CComponent, virtual public A, virtual public B
{
public:
  C();
  virtual ~C();
protected:
  // library "plugin" API for C
  void qux() {
    getModCInternal()->doCSomething();
    AComponent::getModAInternal()->doASomething();
    BComponent::getModBInternal()->doBSomething();
    BaseComponent::getModInternal()->doSomething();
  }
private:
  // Component access hidden here
  using CComponent::manageC;
  using CComponent::setCInternal;
  using CComponent::getCInternal;
  using CComponent::getModCInternal;
};
现在,这允许内部代码
static\u cast
dynamic\u cast
确定如何管理实例:

void manageAnInstance(std::shared_ptr<Base> instance)
{
  // If I need to access a base management function, I can static cast
  // since I know all of them are BaseComponent objects
  BaseComponent* base = static_cast<BaseComponent*>(instance.get());
  base->manageComponent();
  base->setInternal(std::make_shared<BaseInternal>());
}

void manageDerivedStuff(std::shared_ptr<Base> instance)
{
  // If I need to access a derived management function, I need to dynamic
  // cast because I don't know for sure that the instance is one of those
  // classes
  C* c = dynamic_cast<C*>(instance.get());
  if(c)
  {
    CComponent* ccomp = static_cast<CComponent*>(c);
    ccomp->manageC();
    ccomp->setCInternal(std::make_shared<CInternal>());
  }

  A* a = dynamic_cast<A*>(instance.get());
  if(a)
  {
    AComponent* acomp = static_cast<AComponent*>(a);
    acomp->manageA();
    acomp->setAInternal(std::make_shared<AInternal>());
  }
}
void manageAnInstance(std::shared_ptr实例)
{
//如果我需要访问基本管理功能,我可以使用静态强制转换
//因为我知道它们都是BaseComponent对象
BaseComponent*base=static_cast(instance.get());
base->manageComponent();
base->setInternal(std::make_shared());
}
void manageDerivedStuff(std::shared_ptr实例)
{
//如果我需要访问派生的管理功能,我需要动态
//因为我不确定该实例是否是其中之一
//班级
C*C=dynamic_cast(instance.get());
如果(c)
{
CComponent*CComponent=静态铸件(c);
ccomp->manageC();
ccomp->setCInternal(std::make_shared());
}
A*A=dynamic_cast(instance.get());
如果(a)
{
AComponent*acomp=static_cast(a);
acomp->manageA();
acomp->setAInternal(std::make_shared());
}
}
有几件事我真的不喜欢:

  • dynamic\u cast
    s以确定如何管理实例
  • 管理功能访问限制方法非常可怜。派生类可以通过调用(例如,
    BaseComponent::manageComponent()
    )轻松绕过这些访问限制
  • 组件继承也很奇怪。仅仅为了立即隐藏所有这些函数而公开从基类派生看起来很奇怪。我知道这个想法是为了在组件类和面向公众的类之间传递一个清晰的is-a内部关系,但它看起来仍然很奇怪
我相信这里可能还有其他可以改进的地方

一个考虑过的替代方案是直接(私下)在面向公众的类上定义管理函数定义,然后
friend
调用所有需要使用它们的内部类/函数,但这似乎更糟,也更脆弱


有没有更好的方法来完成这类事情?

您的问题非常广泛,因为这不仅仅是一个编程问题,而是一个需求问题,即软件工程问题。试着为我们和你解决这个问题,同时说明你想要什么,而不是你拥有什么。你发布的代码数量很大,不清楚是否相关。删除不相关的部分,甚至发布一个附加的UML图。插件有很多方法,你的问题非常广泛,因为它不仅仅是一个编程问题,而是一个需求问题,即软件工程问题。试着为我们和你解决这个问题,同时说明你想要什么,而不是你拥有什么。你发布的代码数量很大,不清楚是否相关。删除不相关的部分,甚至发布一个附加的UML图。插件有很多种方法。
void manageAnInstance(std::shared_ptr<Base> instance)
{
  // If I need to access a base management function, I can static cast
  // since I know all of them are BaseComponent objects
  BaseComponent* base = static_cast<BaseComponent*>(instance.get());
  base->manageComponent();
  base->setInternal(std::make_shared<BaseInternal>());
}

void manageDerivedStuff(std::shared_ptr<Base> instance)
{
  // If I need to access a derived management function, I need to dynamic
  // cast because I don't know for sure that the instance is one of those
  // classes
  C* c = dynamic_cast<C*>(instance.get());
  if(c)
  {
    CComponent* ccomp = static_cast<CComponent*>(c);
    ccomp->manageC();
    ccomp->setCInternal(std::make_shared<CInternal>());
  }

  A* a = dynamic_cast<A*>(instance.get());
  if(a)
  {
    AComponent* acomp = static_cast<AComponent*>(a);
    acomp->manageA();
    acomp->setAInternal(std::make_shared<AInternal>());
  }
}