一. 函数重载的定义
函数重载是指在同一个作用域内 ,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数.重载函数通常用来命名一组功能相似的函数,这样减少了函数名的数量,避免了名字空间污染,对于程序的可读性有很大的好处.
二. 函数重载的条件
- 相同作用域下.所以成员函数和全局函数不会构成函数重载
- 函数的名称相同
- 函数的参数列表不同(参数的个数和参数的类型)
- 函数的返回值可以相同,也可以不同(如果参数相同,名称相同,仅仅是返回值不同,不能构成重载)
- 不能通过访问权限,返回类型,跑出的异常不同而进行重载
三. 函数重载的例子
void func(int a); // 1
void func(double a); // 2
void func(int a,int b); // 3
void func(int a,double b); // 4
bool func(int a,double b); // 5
int func(int a); // 6
1和2构成重载,参数列表不同,一个是int,一个是double.
1和6不构成重载,仅仅是参数列表不同
2和6构成重载
3和4构成重载,参数列表不同
3和5构成重载,参数列表和返回值都不同
4和5不构成重载,仅仅是返回值不同
类的构造函数就是一个很好的函数重载的例子
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
Person()
{
mName = "无名氏";
mAge = 1000;
mSex = "人妖";
mAddress = "天堂";
cout << "Person的无参构造被调用" << endl;
}
Person(string name):mName(name),mAge(1000),mSex("男"),mAddress("不知道")
{
cout << "Person() 的有参构造被调用参数是(string name)" << endl;
}
Person(string name, int age, string sex) :mName(name), mAge(age), mSex(sex)
{
cout << "Person() 的有参构造被调用参数是(string name,int age,string sex)" << endl;
}
Person(string name, int age, string sex, string address) :mName(name), mAge(age), mSex(sex),mAddress(address)
{
cout << "Person() 的全参构造函数被调用" << endl;
}
private:
string mName;
int mAge;
string mSex;
string mAddress;
};
int main()
{
// 调用无参
Person p;
// 调用一个参数的构造函数
Person p1("张三");
// 调用三个参数的构造函数
Person p2("李四", 18, "男");
// 调用四个参数的构造函数
Person p3("王五", 25, "男", "中国!");
system("pause");
return 0;
}
结果 :
四. 函数重写的定义
函数重写,也被称为覆盖,是指子类重新定义父类中的有相同名称和参数的虚函数,主要在继承的关系中出现
五. 函数重写的条件
- 重写的函数和被重写的函数都必须为virtual函数,并分别位于基类和派生类中
- 重写的函数和被重写的函数,函数名和参数必须完全一致
- 重写函数和被重写的函数的返回值相同,要么都返回指针,要不都返回引用.并且派生类虚函数发返回的指针或者引用的类型是基类中被替换的虚函数返回的指针或者引用的类型或者是这个类型的子类型(派生类型)
- 静态方法不能重写,也就是
static
和virtual
不能同时使用final
关键字修饰的虚函数不能被重写
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/
#include <iostream>
using namespace std;
class A {}; // 类A的声明
class B :public A {};// 类B的声明
class Base
{
public:
virtual A &show()
{
cout << "Base::show()被调用!" << endl;
return *(new A);
}
};
class Derived :public Base
{
public:
// 返回值是B类型,B类型是A类型的派生类型
B &show()
{
cout << "Derived::show()被调用!" << endl;
return *(new B);
}
};
int main()
{
Base b;
Derived d;
Base *p = &b;
p->show(); // 调用的是Base()类中的show()
p = &d;
p->show(); // 调用的是Derived()类中的show()
system("pause");
return 0;
}
结果:
六. 函数的重定义
函数的重定义也叫隐藏,子类重新定义父类中的非虚函数,屏蔽了父类的同名函数(相当于是创建了一个新的函数,跟父类无关.)
- 基本条件
- 子类和父类的函数名称相同,参数也相同,父类中的函数不是virtual,父类的函数将被隐藏.
- 子类和父类的函数名称相同,但是参数不同,此时不管父类的函数是不是virtual函数,都将被隐藏.
- 功能
- 指针是什么类型的,就调用哪个类定义的函数,没法实现多态.
- 如果一个指针定义的是某个类型,无论它指向了其他的派生类的类型,它调用的依旧是定义的那个类型的函数
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/
#include <iostream>
using namespace std;
class Base
{
public:
void print_info()
{
cout << "Base:: print_info() 被调用!" << endl;
}
virtual void print_info_2(void)
{
cout << "Base:: 虚函数print_info_2() 被调用!" << endl;
}
};
class Derived :public Base
{
public:
void print_info()
{
cout << "Derived::print_info() 被调用!" << endl;
}
virtual void print_info_2(int a) // 不会发生重写,因为参数不同
{
cout << "Base:: 虚函数print_info_2() 被调用!" << endl;
}
};
int main()
{
// 首先是定义两个对象
Base b;
Derived d;
Base *p; // Base类型的指针
p = &b; // 指向了b
p->print_info(); // 调用的Base里面的函数
p->print_info_2(); // 调用的Base里面的函数
p = &d;
p->print_info(); // 指向改变了,但是依旧调用的是Base::里面的函数
p->print_info_2(); // 指向改变了,但是依旧调用的Base::里面的函数
system("pause");
return 0;
}
结果: