重载&继承&多态

重载

加号重载

对于内置的数据类型,编译器知道怎么搞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
int m_b;
int m_a;
Person operator+ (int n){
Person teep;
teep.m_a = this->m_a+n;
teep.m_b = this->m_b+n;
return teep;
} // 通过成员函数重载 +
//运算符重载也能重载函数重载
};
Person operator+ (Person &p1,Person &p2){
Person teep;
teep.m_a = p1.m_a+p2.m_a;
teep.m_b =p1.m_b + p2.m_b;
return teep;
}

重载左移运算符

1
2
3
4
5
6
ostream &operator<<(ostream &out, Person &p)
{
out << "m_a=" << p.m_a << " m_b=" << p.m_b << endl;
return out;
}

递増运算符重载

一个前置运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Person &operator++()
{
this->m_b++;
this->m_a++;
return *this;
} // 前置++
Person operator++(int)
{ // 返回值是不可以当作函数重载 ,所以int 为占位参数
// 先理录当时结果
Person tmep = *this;
// 后 递増
this->m_b++;
this->m_a++;
return tmep;
}

仿函数

1
2
3
4
5
6
7
8
9
10
11
12
    class Person {
void operator() (int a){
cout << a;
}
}
//调用两种方法
void test01(){
Person b;
b(1);
//第二种用匿名对象
Person()(2);
}

继承

语法

为了减小重复的代码

语法: class 子类 :继承方式 父类

1
2
3
4
5
6
7
8
9
10
class A{
public:
int m_a;
int m_b;
};
class B:public A
{
int m_c;
};

继承方式

继承方式

  1. 公共
  2. 保护
  3. 私有
    如下规则:
  4. 父类中的保护权限儿子都拿不到
  5. 共有的父类的成员权限不变
  6. 保护-> 父有成员权限变为保护(私有同理)

继承中的对象模型

1
2
3
4
5
6
7
8
9
10
11
12
13
class A{
public:
int m_a;
int m_b;
protected:
int m_d;
private:
int m_f;//父类属性能继承,但是编译器给隐藏了 -
};
class B:public A{
int m_c;
};
//一个B类对象大小为 20

继承中构造和析构的顺序

构造 先父再子
析构 先子后父

同名成员

父类同名加作用域

注意:

  1. 如果是同名函数,编译器会隐藏同名函数(包括重载)
  2. 同名成员

多继承语法

class 子类: 继承方式 父类1,继承方式 父类2,继承方式 父类3
{

}

同名加作用域!!!

菱形继承

多态

用法

分为两类:

  1. 静态多态: 函数重载 和运算符重载
  2. 动态多态: 派生类和虚函数实现运行是多态

区别:

  1. 静态多态的函数地址早绑定 (编译阶段)
  2. 动态多态的函数地址晚邦定 (运行阶段)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>
using namespace std;

class dong{
public:
//虚函数
virtual void speak(){
cout << "dong" << endl;
}
};

class Cat :public dong
{
public:
void speak(){
cout << "cat" << endl;
}
};

void dospeak(dong & animal){
animal.speak(); // 动态多态: 有继承,子类要重写父类中的虚函数
//父类的引用(指针)指向子类对象
}
void task01(){
Cat cat;
dospeak(cat);
}
int main(){
task01();
}

多态原理

  1. 虚函数存储一个指针 vfpter指向一个vftable(表内记录虚函数入口地址)
  2. 如果子类重写了虚函数表 那指针指向入口就被重写的函数覆盖了(指向子类入口了)
  3. 当父类指针或者引用指向子类对象时候,发生多态
    1
    2
    father & fathe = son;
    father.speak();

纯虚函数& 抽象类

抽象类:

  1. 只要有一个纯虚函数就叫抽象类
  2. 无法实例化对象
  3. 抽象类的子类 必须要重写父类中的纯虚函数,不然也是抽象类
    1
    virtural void func()=0;//纯虚函数

虚析构和纯虚析构

如果子类中有属性开辟到堆区 ,那么父类指针在释放时无法调用到子类的析构代码


重载&继承&多态
http://example.com/posts/223.html
作者
yunjianworld
发布于
2024年4月13日
许可协议