4

如何在 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) );
    }
}

编辑2

我为什么要这样做?

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

4

3 回答 3

6

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

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

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

于 2010-09-17T20:06:42.873 回答
3

您可以只使用 C 风格的演员表。不需要任何“黑客”或“实施”。将它包装成一个显式函数服务于“C-Style casts are bad”的人

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.

于 2010-09-17T20:06:37.253 回答
0

我有一个用例;我继承了一个大型且易变的基类,该基类一直在添加函数,而且基类函数几乎永远不会在我的子类中正常工作,所以我私下继承。

我认为创建一个返回基类的函数是最简单的。下面我列出了一个完全更正的程序;请在提交问题之前尝试编译您的代码,因为使用诸如“do”之类的标识符作为函数名称可能会使每个编译器都不满意.. :-( :-(

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() );
  }
};

于 2015-04-22T21:12:59.560 回答