如何在C ++中实现对私有基类的转换

时间:2010-09-17 19:57:20

标签: c++ casting base-class

如何在C ++中实现对私有基类的转换?我不想使用诸如添加朋友之类的黑客。定义公共投射操作符不起作用。

编辑:

例如我有:

class A {
//base class
}

class AX : private A {
//a child
}

class AY : private A {
//another specialized child
}

class B {
//base class
void do (A a) {//do
    }
}

class BX : private B {
//a child
void do (AX a) {
     B::do( static_cast <A> (a) );
    }
}

class BY : private B {
//another specialized child
void do (AY a) {
    B::do( static_cast <A> (a) );
    }
}

EDIT2

为什么我这样做?

假设我必须定义一些非常重量级的属性,并且可以是几种类似的类型(如VelocityX VelocityY等)。然后我希望能够拥有可以拥有任何这些属性集的类。如果我想处理这些属性,很明显,我宁愿将它们转换为基类型,而不是为每个变体添加一个实现。我不使用公共继承,因为最好在需要的地方显式转换,而不是私有接口隐式可见。这不是一个真正的问题,但我希望有一个解决方案:)

3 个答案:

答案 0 :(得分:6)

如果定义公共强制转换操作符不起作用,可以尝试使用常规函数:

class D: private B {
    public:
        B& asB() { return static_cast<B&>(*this); }
};
...
D d;
d.asB().methodInB();
...

无论如何,重点是什么?如果D私密地从B派生,那么您不应该从外部使用D作为B

答案 1 :(得分:4)

你可以使用C风格的演员表。不需要任何“黑客”或“实施”。将它包装成一个显式函数服务于“C风格演员是坏人”

template<typename Targ, typename Src>
typename boost::enable_if<boost::is_base_of<Targ, Src>, Targ>::type &
private_cast(Src &src) { return (Targ&)src; }

要使演员安全,您需要确保Targ实际上是私人或公共基地。这是由boost::is_base_of完成的。


当然,您应该更喜欢返回基指针的相应派生类中的成员函数,而不是执行此类强制转换。


  

定义公共投射操作符不起作用。

这对我来说没有意义......为什么要让基类保密?把它公之于众。转换函数不起作用的原因是标准要求隐式转换从不考虑将转换函数转换为基类,类本身或void

答案 2 :(得分:0)

我有一个用例;我继承了一个大而易变的基类,它一直在添加函数,几乎从来就不是基类函数在我的子类中正常工作,所以我私下继承。

我认为只做一个返回基类的函数是最简单的。下面我列出了一个完全纠正的程序;请在提交问题之前尝试编译代码,因为使用的标识符如&#34; do&#34;因为函数名可能会让每个编译器都不高兴.. :-(: - (

&#13;
&#13;
class A {
  //base class                                                                                                                                                          
};

class AX : private A {
  //a child                                                                                                                                                             
 public:
  A *ToA() { return this; }
};

class AY : private A {
  //another specialized child                                                                                                                                           
 public:
  A *ToA() { return this; }
};

class B {
  //base class                                                                                                                                                          
 protected:
  void do_it (A a) {};
};

class BX : private B {
  //a child                                                                                                                                                             
  void do_it (AX a) {
    B::do_it( *a.ToA() );
  }
};

class BY : private B {
  //another specialized child                                                                                                                                           
  void do_it (AX a) {
    B::do_it( *a.ToA() );
  }
};
&#13;
&#13;
&#13;