C ++结构继承

时间:2017-09-21 08:14:50

标签: c++ inheritance struct

据我所知,C ++中类和结构之间的主要区别(可能是唯一的区别)是默认情况下类的成员是私有的,默认情况下结构都是公共的。

然而,可能因为我以前是一名C级开发人员,我仍然继续申报结构只能公开"公共"字段,我几乎从不声明方法(构造函数除了初始化成员)。

我也想利用结构的C ++继承。

我的问题是:

  1. 即使语言允许,继承结构也是一种好习惯吗?
  2. 是否可以阻止struct声明一个虚方法,该方法将创建一个vtable并修改结构的大小?
  3. 谢谢

6 个答案:

答案 0 :(得分:7)

  

默认情况下,类的成员都是私有的,默认情况下结构都是公共的。

Structs默认继承public,默认情况下类继承private。

Even if the language allows it, is it a good practice to inherits structs ?

不确定。它完全按照您的预期运作。

  

是否可以阻止struct声明一个虚方法,该方法将创建一个vtable并修改struct的大小?

还没有。有一个C ++ 20 +(P0707)的提议允许这一点,但它仍然很年轻,并没有实现足够远,无法在任何地方使用。特别是,搜索" 3.6 plain_struct"看看他们如何强制执行简单的结构。

一般情况下,当你将它作为" struct"一种功能 - 保持没有不变量的数据。如果你有不变量,你应该使用封装和数据隐藏它们,所以它应该是一个类。

答案 1 :(得分:4)

只想解决这个问题:

  

即使语言允许,继承结构也是一种好习惯吗?

你应该摆脱" struct"表示POD。有时候,尽管有一些行为,最可重复使用的组件是那些不会封装任何东西的组件。

例如,考虑这个元函数:

template<typename T> struct is_foo :      std::false_type {};
template<>           struct is_foo<Foo> : std::true_type  {};

使用struct关键字声明所有上述类型(以及true和false别名后面的类型)。这只是因为默认情况下将所有内容公开转发我们想要的行为,而不必每次都拼出来。

另一次你发现自己继承了&#34; struct&#34;是扩展C库的时候。如果库定义了一个名为struct Bar的结构,用于与之通信,那么向其添加功能的最简单方法是继承自Bar。像这样:

class ExtendedBar : Bar {
  void mem_func() {
    //Need to call the C library function? No problem
    c_library_func(this); // ExtendedBar is-a Bar
  }
};

唯一重要的区别是默认的辅助功能级别。您应该关注的唯一事情(IMO)是哪种默认可访问性最适合您的目的。

答案 2 :(得分:2)

  

即使语言允许,继承结构也是一种好习惯吗?

是的。只需看看C ++ STL(标准模板库)。你会发现丰富的结构。

  

是否可以阻止struct声明一个虚方法,该方法将创建一个vtable并修改struct的大小?

No ....截至目前..一旦声明虚函数..将为struct创建vtable

答案 3 :(得分:1)

  

据我所知,C ++中类和结构之间的主要区别(可能是唯一的区别)是默认情况下类的成员是私有的,默认情况下结构都是公共的。

使用关键字struct声明的类与使用关键字class声明的类之间的唯一区别确实是默认访问说明符(它也适用于基数和成员)。

事实上,理解结构的最简单方法是理解它们是类。

  

即使语言允许,继承结构也是一种好习惯吗?

不确定。继承一个类是可以的,结构就是类。

  

是否可以阻止struct声明一个虚方法,该方法将创建一个vtable并修改struct的大小?

不,据我所知,没有这样的功能。

答案 4 :(得分:1)

结构与类

你是对的,C ++中struct和class之间的主要区别是默认访问级别。如果没有显式访问修饰符,则类成员是私有的,而struct成员是public。也可以使用访问修饰符将Struct成员设为私有。请记住,这也适用于继承的类和结构。

至于一般建议:有很多人坚持使用结构只用于行为的所有数据和类[1]。换句话说,POD(普通旧数据)类型的结构[2]。这是一种非常常见的做法。这并不意味着您无法获得与访问和设置数据成员,设置构造函数,析构函数等相关的功能。&#34;如果需要更多功能,则更适合使用类。如果有疑问,可以上课。&#34;他们的指南还建议使用结构而不是函子和特征的类。

您必须牢记,除了任何技术上的优势或缺点之外,还有其他原因可以在团队和项目基础上强制执行特定的实践和标准。正如Google的样式指南中所提到的,我们可以将自己的语义含义添加到我们使用的数据结构中。作为团队成员,我想知道结构是否有行为。例如,知道所有结构都只是POD类型会很高兴。

联合攻击战斗机编码标准指定&#34;应该使用结构来建模不需要不变量的实体。&#34;虽然&#34;应该使用一个类来模拟维持不变量的实体。&#34;公共和受保护的数据应仅用于结构,而不是类。他们的理由是,一个班级无法控制对公共成员的访问;因此,一个类中的所有数据都应该是私有的。在决定编码标准时,必须始终考虑项目的需求。

结构继承

在考虑继承时,您必须考虑公共继承对私有继承的意义。您必须记住新派生的访问级别将具有哪些访问级别,以及继承结构是否有意义。可以将Struct成员设为私有成员,如果您继承此成员,则派生成员将无法访问基础的私有成员。

struct base {   
    int public_data;

    private:
        int private_data;
};

struct derived : base { 
    derived() {
        public_data = 1;
        // private_data = 1;    // no access, won't compile
    }
};

换句话说,继承可能被认为是一个逻辑问题而不是实现问题。

从技术上讲,继承结构没有任何根本性的错误。这可能是一种仁慈的做法,在某些情况下,它可能是有益的并且很有意义。

请记住,在C ++中,结构可以从类继承,反之亦然。

有关vtable的更多信息,请参阅此问题:When is a vtable created in C++?

[1] https://google.github.io/styleguide/cppguide.html#Structs_vs._Classes

[2] http://en.cppreference.com/w/cpp/concept/PODType

答案 5 :(得分:-3)

鉴于struct A { ... };struct B { A a; ... }struct B : A { ... }更安全。

我建议不继承比继承非虚析构函数更好。您唯一丢失的是从B*B&A*A&等的隐式转换。但是,对于这些情况,您仍然有明确的B b; b.a