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