代码之家  ›  专栏  ›  技术社区  ›  user283145

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

  •  1
  • user283145  · 技术社区  · 14 年前

    如何在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等)。然后我希望能够有类,这些类可以有任何一组这些属性。如果我想处理这些属性,很明显,我宁愿将它们强制转换为它们的基类型,而不是为每个变体添加一个实现。我不使用公共继承,因为在需要的地方显式强制转换比隐式显示私有接口更好。不是真正的问题,但我想有一个解决方案:)

    3 回复  |  直到 9 年前
        1
  •  6
  •   gpeche    14 年前

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

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

    不管怎样,有什么意义?如果 D 私人来源 B 那么你不应该使用 D 作为一个 从外面。

        2
  •  4
  •   Johannes Schaub - litb    14 年前

    您可以使用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 .

        3
  •  0
  •   user216843    9 年前

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

    我认为创建一个返回基类的函数是最简单的。下面我列出了一个完全正确的程序;请在提交问题之前尝试编译代码,因为使用诸如“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() );
      }
    };