【问题标题】:Default inheritance access specifier默认继承访问说明符
【发布时间】:2011-06-15 08:53:52
【问题描述】:

例如,如果我有两个类AB,则类B 继承A 如下:

class B: public A

在这种情况下,我正在做public 继承。

如果我把前面的代码写成如下:

class B: A

我将在这里进行什么类型的继承(即公开)?换句话说,默认访问说明符是什么?

这里只是一个附带问题。我是否调用上一行代码statements?特别是我记得我在C++无恐惧:让你感觉聪明的初学者指南一书中读到statements是以;结尾的。你怎么看?

谢谢。

【问题讨论】:

标签: c++ inheritance


【解决方案1】:

只是对所有现有答案的一个小补充:继承的默认类型取决于继承(派生)类型(示例中为B),而不是被继承的类型(基础)(@987654322 @ 在示例中)。

例如:

class A {};
struct B: /* public */ A {};
struct A {};
class B: /* private */ A {};

【讨论】:

  • 我相信(至少它是 Clang 所做的)术语是“标签”(指的是类/结构/联合之一的项目)——也就是说,默认继承类型由继承类型的标签类型(标签种类?)决定。
【解决方案2】:

对于类是私有的,对于结构是公有的。

侧面回答:不,这些是根据标准的类的定义。类定义以分号结尾。另一方面,并​​非所有语句都以分号结尾(例如,if 语句没有)。

【讨论】:

    【解决方案3】:

    当您从另一个类继承一个类时(在这种情况下从class Derived 继承class Base),则默认访问说明符是private

    #include <stdio.h>
    
    class Base {
    public:
    int x;
    };
    
    class Derived : Base { }; // is equilalent to class Derived : private Base       {}
    
    int main()
    {
     Derived d;
     d.x = 20; // compiler error becuase inheritance is private
     getchar();
     return 0;
    }
    

    当您从结构继承类时(在本例中从 struct Derived 继承 class Base),则默认访问说明符为 public

    #include < stdio.h >
      class Base {
        public:
          int x;
      };
    
    struct Derived: Base {}; // is equilalent to struct Derived : public Base {}
    
    int main() {
      Derived d;
      d.x = 20; // works fine becuase inheritance is public
      getchar();
      return 0;
    }
    

    【讨论】:

      【解决方案4】:

      如果您使用class 定义您的类,默认访问说明符将是private。 (我也认为这是错误的。)但是,如果您使用struct,它将是public

      我认为,类定义是声明。语句就是转化为实际代码的内容(除非经过优化,否则)。
      然而,C 和 C++ 的一个有点奇怪的特性是表达式是语句。这就是为什么3+4; 在 C++ 中是一个语法上合法的声明(尽管许多编译器会警告它没有效果)。虽然在这种情况下显然是无稽之谈,但通常会评估表达式的副作用。 (一个明显的例子是丢弃函数的返回值。你调用函数不是为了获得结果,而是为了它的副作用。)

      【讨论】:

      • “语句是翻译成实际代码的东西” 不。在 C++ 中,typedef 是一个语句,它本身并不对应于任何生成的代码。 C++ 认为是语句的内容与 C 认为是语句的内容不同。 stackoverflow.com/a/49862170“表达式是语句”不。分号运算符具有从表达式创建语句并丢弃表达式结果的效果。 informit.com/articles/article.aspx?p=2472079&seqNum=4“一般来说,表达式是针对它们的副作用进行评估的”不。例如,算术。
      • 您认为类的默认访问说明符为 private 有什么问题?
      • @amn:当我写一个类时,我把公共部分放在上面,而不是私人部分,因为公共部分是每个人都应该感兴趣的。所以我可以(几乎)从不使用默认访问说明符。
      【解决方案5】:

      继承的“类型”取决于类的定义方式。有应用于继承的默认访问说明符。来自 C++ 标准:

      [class.access.base]/2

      在基类没有访问说明符的情况下,public 是 当派生类使用类键 struct 定义时假定 当使用 class-key 定义类时,假定为 private class。 [ 示例:

      class B { /* ... */ };
      class D1 : private B { /* ... */ };
      class D2 : public B { /* ... */ };
      class D3 : B { /* ... */ };             // B private by default
      struct D4 : public B { /* ... */ };
      struct D5 : private B { /* ... */ };
      struct D6 : B { /* ... */ };            // B public by default
      class D7 : protected B { /* ... */ };
      struct D8 : protected B { /* ... */ };
      

      这里 B 是 D2、D4 和 D6 的公共基础,D1、D3 的私有基础, 和 D5,以及 D7 和 D8 的受保护基。 — 结束示例 ]

      【讨论】:

        【解决方案6】:

        如果不选择继承,C++ 默认使用private 继承,就像类成员默认使用private 对类的访问一样。

        【讨论】:

          【解决方案7】:

          C++ 中默认的继承类型是private

          class B:A
          {};
          

          等价于

          class B: private A
          {};
          

          【讨论】:

          • 由于问题要求默认继承访问说明符并且没有将问题的域限制为class,因此一般的答案是考虑struct 的继承。如果子类型是struct,则默认继承类型是public。
          【解决方案8】:

          默认访问说明符是类和结构之间的重要区别。默认情况下,它对于结构是公共的,对于类默认是私有的。

          【讨论】:

            【解决方案9】:

            作为您遇到的其他铸造问题

            class A { virtual void test() = 0; };
            class B : virtual public A { virtual void testb() {} };
            class C : virtual public A { virtual void testc() {} };
            class D : public B, public C {
             virtual void test() override {}
            }
            
            void main() {
               D d;
               void* v = &d;
               A* a = &d;
            
               ((D*)A)->test(); //OK
               ((D*)v)->test(); //undefined behavior (that call testb() in vtable logic at 1st inheritance position)
               dynamic_cast<D*>(v)->test(); //compile error cast from void* not permitted
            
               //resolution
               void* x = a;
               ((D*)x)->test(); //OK but as you can see, you must to store a* in x*
            
            }
            

            【讨论】:

              猜你喜欢
              • 2016-01-15
              • 2013-12-25
              • 2011-04-18
              • 1970-01-01
              • 2021-06-10
              • 2012-12-14
              • 2012-04-09
              • 2013-12-05
              • 2017-01-12
              相关资源
              最近更新 更多