学习c++ 第四天 类 及类的继承--class和struct的区别--static成员

Posted 蚁人日记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习c++ 第四天 类 及类的继承--class和struct的区别--static成员相关的知识,希望对你有一定的参考价值。

C++ 类

类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量;创建对象的过程也叫类的实例化。每个对象都是类的一个具体实例(Instance),拥有类的成员变量和成员函数。

注意在类定义的最后有一个分号;,它是类定义的一部分,表示类定义结束了,不能省略。

类只是一个模板(Template),编译后不占用内存空间,所以在定义类时不能对成员变量(除了声明变量外还可以定义方法)进行初始化,因为没有地方存储数据。只有在创建对象以后才会给成员变量分配内存,这个时候就可以赋值了。

创建对象以后,可以使用点号.来访问成员变量和成员函数,这和通过结构体变量来访问它的成员类似

public 成员可以通过对象来访问,protected ,private 成员不能通过对象访问。

对象指针

通过对象名字访问成员使用点号.,通过对象指针访问成员使用箭头->,(this 只能用在类的内部,this 是一个指针,要用->来访问成员变量或成员函数。而对象指针可以在类的外部引用成员变量或成员函数


struct 结构体

C/C++ 允许数组定义可存储相同类型数据项的变量 ,如要存储不同类型的数据项则要使用到[ struct ]

struct struct_name

member_type1 member_name1;

member_type2 member_name2;

member_type3 member_name3;

struct_object_names;

//如示例
struct Books

   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
 book;

为了访问结构的成员,我们使用成员访问运算符(.)。与类的对象访问成员一样 


类的继承(c++可以多继承,java 不是能多继承)

class 派生类名:继承方式] 基类名
    派生类新增加的成员
;

继承方式限定了基类成员在派生类中的访问权限,包括 public(公有的)、private(私有的)和 protected(受保护的)。此项是可选项,如果不写,默认为 private(成员变量和成员函数默认也是 private)。

基类中的 protected 成员可以在派生类中使用,而基类中的 private 成员不能在派生类中使用,

1) public继承方式

  • 基类中所有 public 成员在派生类中为 public 属性;
  • 基类中所有 protected 成员在派生类中为 protected 属性;
  • 基类中所有 private 成员在派生类中不能使用。


2) protected继承方式

  • 基类中的所有 public 成员在派生类中为 protected 属性;
  • 基类中的所有 protected 成员在派生类中为 protected 属性;
  • 基类中的所有 private 成员在派生类中不能使用。


3) private继承方式

  • 基类中的所有 public 成员在派生类中均为 private 属性;
  • 基类中的所有 protected 成员在派生类中均为 private 属性;
  • 基类中的所有 private 成员在派生类中不能使用。


通过上面的分析可以发现:
1) 基类成员在派生类中的访问权限不得高于继承方式中指定的权限。也就是说,继承方式中的 public、protected、private 是用来指明基类成员在派生类中的最高访问权限的。

2) 不管继承方式如何,基类中的 private 成员在派生类中始终不能使用(不能在派生类的成员函数中访问或调用)。

3) 如果希望基类的成员能够被派生类继承并且毫无障碍地使用,那么这些成员只能声明为 public 或 protected;只有那些不希望在派生类中使用的成员才声明为 private。

4) 如果希望基类的成员既不向外暴露(不能通过对象访问),还能在派生类中使用,那么只能声明为 protected。

注意,我们这里说的是基类的 private 成员不能在派生类中使用,并没有说基类的 private 成员不能被继承。实际上,基类的 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,导致无法使用罢了。

多继承

//间接基类A
class A
protected:
    int m_a;
;

//直接基类B
class B: public A
protected:
    int m_b;
;

//直接基类C
class C: public A
protected:
    int m_c;
;

//派生类D
class D: public B, public C
public:
    void seta(int a) m_a = a;   //命名冲突
    void setb(int b) m_b = b;   //正确
    void setc(int c) m_c = c;   //正确
    void setd(int d) m_d = d;   //正确
private:
    int m_d;
;

int main()
    D d;
    return 0;

 这段代码实现了上图所示的菱形继承,第 25 行代码试图直接访问成员变量 m_a,结果发生了错误,因为类 B 和类 C 中都有成员变量 m_a(从 A 类继承而来),编译器不知道选用哪一个,所以产生了歧义。

为了消除歧义,我们可以在 m_a 的前面指明它具体来自哪个类:

void seta(int a) B::m_a = a;

这样表示使用 B 类的 m_a。当然也可以使用 C 类的:

void seta(int a) C::m_a = a;


虚继承 

为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员

在继承方式前面加上 virtual 关键字就是虚继承,请看下面的例子:

//间接基类A
class A
protected:
    int m_a;
;

//直接基类B
class B: virtual public A  //虚继承
protected:
    int m_b;
;

//直接基类C
class C: virtual public A  //虚继承
protected:
    int m_c;
;

//派生类D
class D: public B, public C
public:
    void seta(int a) m_a = a;   //正确
    void setb(int b) m_b = b;   //正确
    void setc(int c) m_c = c;   //正确
    void setd(int d) m_d = d;   //正确
private:
    int m_d;
;

int main()
    D d;
    return 0;

虚继承的目的是让某个类做出声明,承诺愿意共享它的基类。其中,这个被共享的基类就称为虚基类(Virtual Base Class),本例中的 A 就是一个虚基类。在这种机制下,不论虚基类在继承体系中出现了多少次,在派生类中都只包含一份虚基类的成员。


在C++中,struct 类似于 class,既可以包含成员变量,又可以包含成员函数。

C++中的 struct 和 class 基本是通用的,唯有几个细节不同:

  • 使用 class 时,类中的成员默认都是 private 属性的;而使用 struct 时,结构体中的成员默认都是 public 属性的。
  • class 继承默认是 private 继承,而 struct 继承默认是 public 继承
  • class 可以使用模板,而 struct 不能

Static 

在C++中,我们可以使用静态成员变量来实现多个对象共享数据的目标。静态成员变量是一种特殊的成员变量,它被关键字static修饰, 

static 成员变量属于类,不属于某个具体的对象,即使创建多个对象,也只为static变量分配一份内存,所有对象使用的都是这份内存中的数据。当某个对象修改了static变量也会影响到其他对象,

static 成员变量必须在类声明的外部初始化,具体形式为:

type class::name = value;

type 是变量的类型,class 是类名,name 是变量名,value 是初始值。

静态成员变量在初始化时不能再加 static,但必须要有数据类型。被 private、protected、public 修饰的静态成员变量都可以用这种方式初始化。

static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。反过来说,没有在类外初始化的 static 成员变量不能使用。static变量都在内存分区中的全局数据区分配内存,到程序结束时才释放。这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。

static 成员变量既可以通过对象来访问,也可以通过类来访问。

//通过类Student 类访问 static 成员变量
Student::m_total = 10;
//通过对象来访问 static 成员变量
Student stu("小明", 15, 92.5f);
stu.m_total = 20;
//通过对象指针来访问 static 成员变量
Student *pstu = new Student("李华", 16, 96);
pstu -> m_total = 20;

static 成员变量不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问(而this是必须在创建类对象之后才可能使用)

以上是关于学习c++ 第四天 类 及类的继承--class和struct的区别--static成员的主要内容,如果未能解决你的问题,请参考以下文章

第二十四天 PYTHON学习

Python中类的继承及类的属性和方法总结

如何在 C++ 中解决网格继承问题

OC第四天笔记2016年03月18日(周五)A.M

概述类的加载器及类加载过程

概述类的加载器及类加载过程