设为首页 加入收藏

TOP

继承和多重继承(一)
2023-07-23 13:38:45 】 浏览:205
Tags:

一、继承的基本概念

? 继承:子类继承父类的属性和行为

? 作用:代码复用

继承分类:

1. 按访问属性分为public、private、protected三类

1)public: 父类属性无更改,pubic, private, protected 仍是自己本身(子类成员函数可以访问父类的public和protected,子类对象可以访问public)

2)private: 父类属性全变为privates(子类不能访问父类属性)

3)protected: 父类public变为protected,其他不变(子类成员函数可以访问父类的public和protected,子类对象不能访问)

2. 按继承父类的个数分为单继承和多继承

类的成员函数由所有对象共享,但是每个对象有单独的成员变量,所以利用sizeof(对象时),字节数为所有成员变量的大小

普通继承:子类继承父类即继承父类的所有属性及行为,当多继承时,有父类的父类的两份拷贝

虚继承:菱形继承,共享一个虚基类

二、类与类的关系

1. 父类和子类

普通继承:先执行父类构造函数,再执行子类构造函数;先执行子类析构函数,再执行父类析构函数

1)当子类中没有构造函数或析构函数,父类却需要构造函数和析构函数时,编译器会为子类提供默认的构造函数与析构函数以调用父类的构造和析构函数

2)子类的内存结构:子类继承父类,类似在子类中定义了父类的对象,如此当产生Derive类的对象时,会先产生成员对象base,这需要调用其构造函数

? 当Derive类没有构造函数时,为了能够在Derive类对象产生时调用成员对象的构造函数,编译器同样会提供默认的构造函数,以实现成员构造函数的调用

class Base{...}; 
class Derive  {
public:
  Base base; //原来的父类Base 成为成员对象 
  int derive; // 原来的子类派生数据
};

3)子类内存中的数据排列:先安排父类的数据,后安排子类新定义的数据

注意:当子类中有构造函数,父类无构造函数,不会给父类提供默认的构造函数

普通子类继承父类 c++ 代码示例:

#include <stdio.h> 
class Base {  //基类定义
public: 
  Base() {
    printf("Base\n"); 
  }
  ~Base() {
    printf("~Base\n"); 
  }
  void setNumber(int n) { 
    base = n;
  }
  int getNumber() { 
    return base; 
  }
public: 
  int base; 
};
class Derive : public Base  {  //派生类定义 
public:  void showNumber(int n) { 
    setNumber (n);
    derive = n + 1;
    printf("%d\n", getNumber()); 
    printf("%d\n", derive);
  }
public:
  int derive; 
};
int main(int argc, char* argv[]) { 
  Derive derive;
  derive.showNumber(argc); 
  return 0;
}

汇编标识:

00401000  push    ebp
00401001  mov     ebp, esp
00401003  sub     esp, 0Ch
00401006  lea     ecx, [ebp-0Ch]    ;获取对象首地址作为this指针
00401009  call    sub_401050        ;调用类Derive的默认构造函数 ①
0040100E  mov     eax, [ebp+8]
00401011  push    eax               ;参数2:argc
00401012  lea     ecx, [ebp-0Ch]    ;参数1:传入this指针
00401015  call    sub_4010E0        ;调用成员函数showNumber ②
0040101A  mov     dword ptr [ebp-4], 0
00401021  lea     ecx, [ebp-0Ch]    ;传入this指针
00401024  call    sub_401090        ;调用类Derive的默认析构函数 ③
00401029  mov     eax, [ebp-4] 
0040102C  mov     esp, ebp
0040102E  pop     ebp
0040102F  retn

00401050  push    ebp               ;子类Derive的默认构造函数分析
00401051  mov     ebp, esp
00401053  push    ecx
00401054  mov     [ebp-4], ecx
00401057  mov     ecx, [ebp-4]      ;以子类对象首地址作为父类的this指针 ①
0040105A  call    sub_401030        ;调用父类构造函数
0040105F  mov     eax, [ebp-4]
00401062  mov     esp, ebp
00401064  pop     ebp
00401065  retn

00401090  push    ebp               ;子类Derive的默认析构函数分析
00401091  mov     ebp, esp
00401093  push    ecx
00401094  mov     [ebp-4], ecx
00401097  mov     ecx, [ebp-4]      ;以子类对象首地址作为父类的this指针 ①
0040109A  call    sub_401070        ;调用父类析构函数
0040109F  mov     esp, ebp
004010A1  pop     ebp
004010A2  retn

? 子类中定义了其他对象作为成员,并在初始化列表中指定了某个成员的初始化值时:先构造父类,然后按声明顺序构造成员对象和初始化列表中指定的成员,最后构造自己

类中定义了其他对象作为成员,并在初始化列表中指定了某个成员的初始化值时的 c++ 示例代码:

class Member{ 
public:
  Member()  { 
    member = 0; 
  }
  int member; 
};
class Derive : public Base  { 
public:
  Derive():derive(1)  { 
    printf("使用初始化列表\n"); 
  }
public:
  Member member;  //类中定义其他对象作为成员 
  int derive;
};
int main(int argc, char* argv[]) { 
  Derive derive;
  return 0; 
}

汇编标识:

00401000  push    ebp
00401001  mov     ebp, esp
00401003  sub     esp, 10h
00401006  lea     ecx, [ebp-10h]       ;传递this指针
00401009  call    sub_401050           ;调用Derive的构造函数 ①
0040100E  mov     dword ptr [ebp-4], 0
00401015  lea     ecx, [ebp-10h]       ;传递this指针
00401018  call    sub_4010D0           ;调用Derive的析构函数 ⑥
0040101D  mov     eax, [ebp-4]
00401020  mov     esp, ebp
00401022  pop     ebp
00401023  retn

00401050  push    ebp                  ; Derive构造函数
00401051  mov     ebp, esp
00401053  push    ecx
00401054  mov     [e
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇c++学习笔记——模板和IO(二) 下一篇P1219 [USACO1.5]八皇后 Checker ..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目