函数重载和运算符重载属于静态多态,因为它们属于复用了函数名,使用的是函数重载
函数重载:
- 函数的返回值类型不能作为重载条件
int chongzai(){};
void chongzai(){};
#以上两者不属于重载函数
- 函数重载的形参数量不同
- 函数的函数名字相同
- 函数的形参类型不同
void chongzai(){};
void chongzai(int){};
#第二个函数中使用了占位参数,来达到函数重载的条件
void chongzai(float){};
void chongzai(int){};
#两个函数形参类型不同,达到函数重载的条件
继承中的函数重载
继承中用到函数重载的情况一般是在父类种,有同名的成员函数,当子类继承父类之后,想调用父类中的第二个或者第n个同名函数,需要加作用域,并且父类中的需要进行函数重载。
当子类中出现和父类同名的成员函数,子类的同名成员函数会隐藏掉父类中所有的同名成员函数,隐藏了重载的所有函数,如果想访问被隐藏的同名函数,需要在函数名前面加上父类的作用域。
#include <iostream>
using namespace std;
//继承中同名成员中的处理
class Base
{
public:
Base()
{
m_a = 100;
m_b = 200;
}
//父类中出现了同名函数,使用占位参数作为函数重载的条件
void func()
{
cout << "base作用于下的成员函数" << endl;
}
//同一个作用域下想要使用两个同名函数就需要进行函数重载
void func(int)
{
cout << "base(int)作用于下的成员函数" << endl;
}
int m_a;
int m_b;
};
class son1 :public Base
{
public:
son1()
{
m_a = 200;
}
void func()
{
cout << "son作用于下的成员函数" << endl;
}
int m_a;
};
//当子类继承父类之后,若不加作用域,则无法访问到父类中的重载函数
void test02()
{
son1 s1;
//访问子类
s1.func();
//访问父类
//加上作用域
s1.Base::func();
s1.Base::func(100);
}
//同名成员函数的处理方式
int main()
{
test02();
system("pause");
return 0;
}
多态中的函数重写
实现多态所需要满足的条件就是:
- 有继承的关系
- 子类需要重写父类的虚函数
有继承关系就是,需要有一个子类继承父类的关系。当存在子类继承父类关系之后,就需要发生函数重写,也就是父类中的虚函数需要在子类中进行重写。
- 虚函数
虚函数的用法就是,在函数名或者函数的返回值类型名前加上virtual关键字
virtual void xuhanshu(){};
当父类中定义了虚函数,子类继承父类之后,虚函数一般情况下就不会再被实现,因此也不 需要担心类内函数同名的情况。因为对于父类的虚函数,只是一种声明,实现是在子类当中。
- 子类重写父类的虚函数
整体来看的话,父类中的虚函数只是起到声明的作用,具体实现需要在子类中进行函数重写来完成。
函数重写:返回指定类型 函数名 参数列表 完全相同
#include <iostream>
using namespace std;
//函数重载和运算符重载属于静态多态,复用函数名
//非静态成员函数不在类上储存 空类的字节是1 非静态成员变量在类上储存
class animal
{
public:
virtual void speak()//虚函数
{
cout << "动物在说话" << endl;
}
private:
};
class cat :public animal
{
public:
//函数重写:返回指定类型 函数名 参数列表 完全相同
void speak()
{
cout << "小猫说话" << endl;
}
};
class dog :public animal
{
public:
void speak()
{
cout << "小狗在说话" << endl;
}
};
//执行说话的函数
//地制早绑定 在编译阶段就确定了函数的地址
//如果想执行让猫说话 那么这个函数的地址就不能提前绑定 需要在运行阶段进行绑定
//动态多态满足条件
//1、有继承关系
//2、子类重写父类的虚函数
//动态多态的使用
//父类的指针或引用 执行子类的对象,传入谁就调用谁的函数
//
void dospeak(animal& an)//animal& an = c
{
an.speak();//虚函数的地址不能提前确定,看传入的是哪个对象就走哪个
}
void test01()
{
cat c;
//c.speak();
dospeak(c);
dog d;
dospeak(d);
}
void test02()
{
//当加上virtual之后就变成了四个字节 多了一个指针
cout << "sizeof animal:" << sizeof(animal) << endl;
}
int main()
{
test01();
//test02();
system("pause");
return 0;
}
多态的使用
父类的指针或者引用 指向子类的对象
当子类中重写函数完成之后,想要实现多态,就需要进行父类指针的创建,让指针指向子类的对象名,一般来说可以采用new创建堆区的方法,来创建父类的指针,这样的好处是,可以节省内存空间。
//这里创建了一个cpu类,属于抽象类,父类
class CPU
{
public:
//这个函数属于纯虚函数,只是作为声明,没有实现的功能
virtual void calculate() = 0;
};
//这里创建了一个子类intercpu
class intercpu :public CPU
{
public:
virtual void calculate()
{
cout << "inter的cpu开始工作" << endl;
}
};
//想要实现多态,就需要创建父类指针
void test01()
{
//在堆区上开辟一块内存,让父类的指针inter指向子类,此时已经实现了多态
CPU* inter = new intercpu;
//接着就可以调用calculate()
inter.calculate();
}
#输出
inter的cpu开始工作