【问题标题】:C++ Access derived class member from base class pointerC ++从基类指针访问派生类成员
【发布时间】:2011-01-27 00:37:25
【问题描述】:

如果我分配Derived 类的对象(基类为Base),并将指向该对象的指针存储在指向基类的变量中,我如何访问Derived班级?

这是一个例子:

class Base
{
    public:
    int base_int;
};

class Derived : public Base
{
    public:
    int derived_int;
};

Base* basepointer = new Derived();
basepointer-> //Access derived_int here, is it possible? If so, then how?

【问题讨论】:

    标签: c++ inheritance pointers derived-class


    【解决方案1】:

    不,您不能访问derived_int,因为derived_intDerived 的一部分,而basepointer 是指向Base 的指针。

    你可以反过来做:

    Derived* derivedpointer = new Derived;
    derivedpointer->base_int; // You can access this just fine
    

    派生类继承基类的成员,而不是相反。

    但是,如果您的 basepointer 指向 Derived 的实例,那么您可以通过强制转换访问它:

    Base* basepointer = new Derived;
    static_cast<Derived*>(basepointer)->derived_int; // Can now access, because we have a derived pointer
    

    请注意,您需要先将继承更改为 public

    class Derived : public Base
    

    【讨论】:

    • 他不应该使用dynamic_cast而不是static_cast吗?
    • 这取决于他是否知道这是Derived。如果您 100% 确定(就像我们在这里一样),那么 static_cast 就可以了。
    • 不是每个人的意思都是 reinterpret_cast 而不是 static_cast?我很确定 static_cast 不会编译。
    • @Balk 不,static_cast 在这里是正确的。 reinterpret_cast 会编译,但在许多情况下它会做错事。 reinterpret_cast 不会更改存储在指针中的地址,它只是重新解释它。但是,static_cast 有时需要偏移指针(例如,如果 Derived 从多个基址继承)
    • 首先你不能使用dynami_cast,除非你在处理多态类。这个类没有任何成员函数来真正添加虚拟行为。 static_cast 是给定场景中最好的做法。
    【解决方案2】:

    你在这里的雷区跳舞。基类永远不会知道它实际上是派生的实例。最安全的方法是在基础中引入一个虚函数:

    class Base 
    { 
    protected:
     virtual int &GetInt()
     {
      //Die horribly
     }
    
    public: 
     int base_int; 
    }; 
    
    class Derived : Base 
    { 
      int &GetInt()
      {
        return derived_int;
      }
    public: 
    int derived_int 
    }; 
    
    basepointer->GetInt() = 0;
    

    如果basepointer 指向的不是Derived,那么你的程序将会死得很惨,这是预期的结果。

    或者,您可以使用dynamic_cast&lt;Derived&gt;(basepointer)。但是您至少需要在Base 中添加一个虚函数,并准备好遇到一个零。

    static_cast&lt;&gt;,就像一些人建议的那样,是一种肯定的方式来射击自己的脚。不要为大量“C 语言家族的不安全”恐怖故事做出贡献。

    【讨论】:

    • “或者,您可以使用 dynamic_cast(basepointer)。但您需要在 Base 中至少有一个虚函数,并准备好遇到零。” --> 好点塞瓦。喜欢它:)
    • 使用static_cast 并不是一种自取其辱的方式。我认为您将它与 C 的显式转换符号 (T)x 混淆了。另一方面,static_cast 是类型安全的,但如果dynamic_cast 无法转换,它将返回一个空指针,而static_cast 将发出编译器错误。
    【解决方案3】:

    你可以使用CRTP

    你基本上在基类的模板中使用派生类

    【讨论】:

      【解决方案4】:

      可以通过让基类知道派生类的类型来实现。这可以通过使基类成为派生类型的模板来完成。这个 C++ 习语叫做curiously recurring template pattern

      知道派生类,基类指针可以静态转换为指向派生类型的指针。

      template<typename DerivedT>
      class Base
      {
      public:
          int accessDerivedField()
          {
              auto derived = static_cast<DerivedT*>(this);
              return derived->field;
          }
      };
      
      
      class Derived : public Base<Derived>
      {
      public:
          int field;
      };
      
      int main()
      {
          auto obj = new Derived;
          obj->accessDerivedField();
      }
      

      【讨论】:

        【解决方案5】:

        //如果你知道你要使用什么派生类

        Derived* derivedpointer = dynamic_cast basepointer;

        //然后你可以使用派生指针访问派生类

        【讨论】:

          猜你喜欢
          • 2016-07-31
          • 1970-01-01
          • 2015-02-04
          • 2011-02-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-10
          • 1970-01-01
          相关资源
          最近更新 更多