【问题标题】:C++: Accessing Grandparent MethodC++:访问祖父方法
【发布时间】:2011-06-09 19:44:12
【问题描述】:

为什么这不起作用,什么是好的选择?

class Grandparent
{
    void DoSomething( int number );
};

class Parent : Grandparent
{
};

class Child : Parent
{
    void DoSomething()
    {
        Grandparent::DoSomething( 10 ); // Does not work.
        Parent::DoSomething( 10 ); // Does not work.
    }
};

【问题讨论】:

    标签: c++ inheritance polymorphism overloading


    【解决方案1】:
    class Grandparent
    {
    protected:
        void DoSomething( int number );
    };
    
    class Parent : protected Grandparent
    {
    };
    
    class Child : Parent
    {
        void DoSomething()
        {
            Grandparent::DoSomething( 10 ); //Now it works
            Parent::DoSomething( 10 ); // Now it works.
        }
    };
    

    至少它需要看起来像这样。在使用类时,默认情况下事物是私有的,这包括来自子类。

    http://codepad.org/xRhc5ig4

    有一个完整的例子可以编译和运行。

    【讨论】:

    • 请注意struct 的成员默认是公开的。事实上,classstruct 之间的唯一区别是class 成员默认为私有,struct 成员默认为公开。
    • 是的,我刚刚修复了 OP,我刚刚编译了我的示例并且它可以工作......我需要查看我在实际代码中做错了什么。谢谢。
    • 您是否遇到编译错误?还是在运行时出现问题?
    • @Joshua 我刚刚用 GCC 编译了你的示例。我收到以下错误: temp3.cpp:(.text._ZN5Child11DoSomethingEv[Child::DoSomething()]+0x19): undefined reference to Grandparent::DoSomething(int)' temp3.cpp:(.text._ZN5Child11DoSomethingEv[Child::DoSomething()]+0x2a): undefined reference to Grandparent::DoSomething(int)'
    • 为了记录,面向对象中继承的一般概念通常在C++中实现为public继承。我建议初学者始终使用class Subclass : public Superclass
    【解决方案2】:

    我猜你的代码没有编译 - 错误的主要来源是缺少方法 Child::DoSomething() 的返回类型说明符。

    【讨论】:

    • 不,这不是问题所在。我只是不小心在示例中遗漏了它。
    • @Jay 好的,我一开始就看到了。下一个错误来源是公共继承在子类中隐藏了父类的私有成员,因此您需要提升父类中的访问级别 - 正如 Joshua 的回答中所述
    • 你不是说私有继承吗?
    • @Joshua:哎呀,我忽略了这一点 - 这就是你提升和继承级别的原因
    【解决方案3】:
    class Grandparent
    {
        public:
        void DoSomething( int number ){
            cout<<number;
        }
    };
    
    class Parent : public Grandparent
    {
        public:
        void DoSomething(int x){
            cout<<x<<'\n';
        }
    };
    
    class Child : public Parent
    {
        public:
        void DoSomething()
        {
            Grandparent::DoSomething( 10 ); // works.
            Parent::DoSomething( 10 ); // works.
        }
    };
    

    C++ 中的默认继承类型是私有的,C++ 中的默认成员函数访问说明符也是私有的。因此,在任何情况下都不能访问 GrandParent 类的私有成员。您已将 GrandParent 的 DoSomething() 设为公开或受保护。然后提及适当的继承类型。

    【讨论】:

      【解决方案4】:

      (1) 是的,当我们使用 public 或 protected 访问修饰符继承派生类时,我们只能访问派生类中的祖父母成员。

      (2) 声明为受保护的基类成员在类外不可访问,但该类的任何派生类都可以访问它们。当您通过 public 或 protected 访问修饰符继承基类的受保护成员时,该数据成员访问说明符在派生类中受到保护。

      (3) 默认情况下,访问修饰符在 C++ 中的继承中是私有的,在您给定的示例中。由于您试图访问子类中基类的私有成员,因此必然会产生编译时错误。也请阅读下一点。

      (4) 声明为私有的基类成员当然继承到派生类。但是,无论继承时使用何种访问修饰符,它们都不可访问。这是可用性与可访问性的问题。基类的私有成员可供后续派生类使用,但不可访问。我们可以在私有继承基类之后使用 sizeof(derived class object) 运算符来检查。

      让我们讨论另一件事。我们如何访问基类的私有成员? 好吧,我们可以通过使用友元函数和指针来做到这一点。但是,在基类中声明 Friend 函数取决于该基类的创建者。所以,我们不会在这篇文章中讨论这个。

      class Base
      {
        private : 
                 int x1,x2;
      };
      
      class Derived : public Base
      {
           public : 
                    int x3;
                    void display(int *ptr)
                    {
                         cout << "the value of x1 = " << *(ptr) << endl;
                         cout << "the value of x2 = " << *(ptr+1) << endl;
                         cout << "the value of x3 = " << *(ptr+2) << endl;
                    }
      };
      
      int main()
      {
          Derived d;
          int *ptr = (int *)&d.x3; // typecasting 
      
          *ptr = 3; // setting x3 as 3
           ptr--;
           
          *ptr = 2; // setting x2 as 2
           ptr--;
       
          *ptr = 1; // setting x1 as 1
           ptr--;
      
           d.display(ptr);
           return 0;
      }
      

      我们已经成功访问​​了基类的私有成员。

      我想分享的还有一件事是:如果我们有一个虚拟祖父类,我们可以直接从子类调用祖父构造函数。但一般情况下是不允许直接调用祖父构造函数的,必须通过父类调用。只有在使用虚拟关键字时才允许。

      【讨论】:

        【解决方案5】:

        它的多级继承尝试为您的祖父类提及访问说明符。

        因为默认情况下访问说明符是 PRIVATE,我们将无法访问子类中父类的私有成员。

        【讨论】:

          猜你喜欢
          • 2021-01-11
          • 2011-07-11
          • 1970-01-01
          • 2011-05-30
          • 1970-01-01
          • 2012-04-26
          • 1970-01-01
          • 2015-03-23
          • 2015-03-25
          相关资源
          最近更新 更多