我可以安全地转换为兄弟类来包装受保护的函数吗?

时间:2014-01-14 17:46:19

标签: c++

我在命名空间Util中有许多免费函数,它们在A类上运行,本着正确封装的精神。 A类是一个抽象接口,因此util函数将接收专门的派生变量,例如B.一些自由函数需要访问A中我不想公开的私有方法。这主要是由于A中的不良设计,由于其在更大的组件层次结构中的作用而难以改变。解决方案是将A子类化为Aimpl并编写包装函数,例如:

class A { //Is abstract polymorphic interface
public:
  virtual void SomeFunc() = 0;
protected:
  void ProtectedFunc() {SomeOtherFunc();}
private:
  void SomeOtherFunc();
};

class B : public A { //Overrides stuff in A and has added variables
public:
  virtual void SomeFunc();
};

我在一个单独的文件中定义

namespace {
class Aimpl : public A {
public:
  void WrapProtectedFunc() {ProtectedFunc();}
};
}

namespace Util {
void ProtectedFunc(A& instance) {
  try {
    Aimpl& aimpl = static_cast<Aimpl&>(instance);
    aimpl.WrapProtectedFunc();
  }
  catch (std::bad_cast) {}
}

首先我想使用dynamic_cast,但这显然失败了,因为我可能得到B参考,而B不是Aimpl。但是static_cast和reinterpret_cast工作正常,在Linux gcc4.4上测试过。

我有一种令人毛骨悚然的感觉,我在这里召唤龙。我试图寻找这个,我已经明白这可能实际上是未定义的行为。但它真的吗?当Aimpl只是在界面中添加一个公共函数时,我们能不能保证这个演员会有效吗?

以更好的方式实现这一目标的建议也非常受欢迎。

编辑:

我已经找到了使用友元函数的正确方法,在A头文件中声明了Util函数:

namespace Util {
  void ProtectedFunc(A& instance);
}

class A { //Is abstract polymorphic interface
public:
  virtual void SomeFunc() = 0;
private:
  void SomeOtherFunc();
  friend void Util::ProtectedFunc(A& instance);
};

Util :: ProtectedFunc的定义在cpp文件中,目标已实现;所有用户都可以编写Util :: ProtectedFunc(instance)而不是instance-&gt; ProtectedFunc()。

1 个答案:

答案 0 :(得分:2)

赢了工作。首先,WrapProtectedFunc是私密的,因此您无论如何都无法调用它。 static_cast将编译,但您将获得未定义的行为。这个catch (std::bad_cast) {}毫无意义,因为static_cast永远不会抛出。简单的解决方案:将WrapProtectedFunc作为公共成员添加到A,因为如果您的免费功能需要访问A的内部,那么他们需要访问A的内部。如果A在所有术语中都有任何内部结构&# 34;抽象多态接口&#34;不合适。顺便说一下,你指定的A类既不是抽象的也不是多态的。