1、成员函数的重载
1.1、C++中的成员函数有4种,分别是普通成员函数,virtual虚函数,const成员函数。
- void func(int a)
- virtual void func(int a);
- void func(int a) const;
如果在一个类中,声明这四种函数,哪是重复定义?哪些是重载?其中(1)(2)是重复定义,故编译不能通过,而(3)与(1)(2)是不同类型的函数,是重载。
因为类中的函数,都会自动添加一个自身类指针this,所以
- void func(int a); ------> void func(Base *this, int a)
- virtual void func(int a); ------> virtual void func(Base *this, int a)
- void func(int a) const; ------> void func(const Base *this, int a) const
所以(3)可以和(1)(2)重载,因为参数有一个const
1.2、类的成员函数重载是在同一个类中有多个同名的方法,这些方法的参数类型、参数个数或者方法属性(const)不同。
#define _CRT_SRCURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
public:
MyClass(int a = 0):c(a) {};
void go(int a) { cout << "go "; };
void go(char a){ cout << "char go "; };
void print()const//函数体中不能修改数据成员对象,否则报错
{
cout << "const " << c << endl;
}
void print()//函数体中可修改成员对象
{
c = 23;
cout << "non-const " << c << endl;
}
private:
int c;
};
void main()
{
MyClass my;
my.go(1);
my.print(); //non-const 23
const MyClass myC;
myC.print(); //const 0
system("pause");
}
成员函数重载特征:
- 相同的范围
- 函数名字相同
- 参数类型,个数,顺序不同[包括const参数和非const参数]
- virtual关键字可有可无
2、成员函数的继承
#define _CRT_SRCURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Base
{
public:
void func(int a) { cout << "Base::f(int a)" << endl; };
virtual void go(int a) { cout << "virtual Base: go(int a) " << endl; }; //virtual void func(Base *this, int a)
};
class Deviced :public Base
{
public:
void h(int a) { cout << "Deviced::h(int a)" << endl; };
};
void main()
{
Base b;
b.func(3);
b.go(4);
Deviced d;
d.func(32);
d.go(4);
d.h(32);
system("pause");
}
子类deviced d种继承了父类种的virtual void g(int a), vpid f(int a);
3、成员函数的覆盖
覆盖是指派生类重新实现[或者改写]基类地成员函数,其特征是:
- 不同的作用域
- 函数名称相同
- 参数列表相同
- 基类函数必须是虚函数----->覆盖是针对基函数的
Deviced d种重新定义了基类的虚函数成员virtual void g(int a);
#define _CRT_SRCURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Base
{
public:
void func(int a) { cout << "Base::f(int a)" << endl; };
virtual void go(int a) { cout << "virtual Base: go(int a) " << endl; }; //virtual void func(Base *this, int a)
};
class Deviced :public Base
{
public:
void h(int a) { cout << "Deviced::h(int a)" << endl; };
virtual void go(int a) { cout << "Deviced Base: go(int a) " << endl; };
};
void main()
{
Base b;
b.func(3);
b.go(4);
Deviced d;
d.func(32);
d.go(4);
d.h(32);
system("pause");
}
4、成员函数的隐藏
隐藏是指派生类的成员函数遮蔽了与其同名的基类成员函数:隐藏是在子类中看不到父类的函数
隐藏/重定义:指的是派生类的成员函数隐藏了基类函数的成员函数。
- 在调用一个类的成员函数时候,编译器会沿着类的继承链逐步向上查找函数的定义,如果找到了就停止查找了。
- 如果一个派生类和一个基类都有同一个同名函数,而编译器最后选择了派生类的函数,我们就说这个派生类的成员函数隐藏了基类的成员函数,也就是阻止了编译器继续向上查找函数的定义。
#define _CRT_SRCURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Base {
public:
virtual void f(float x) { cout << "virtual Base::f(float)" << x << endl; }
void g(float x) { cout << "Base::g(float)" << x << endl; }
void h(float x) { cout << "Base::h(float)" << x << endl; }
};
class Deviced :public Base
{
public:
virtual void f(float x) { cout << "virtual Deviced::f(float)" << x << endl; }
void g(int x) { cout << "Deviced::g(int)" << x << endl; }
/*派生类的函数与基类的函数同名不同参,此时,无论有无vritual,*/
void h(float x) { cout << "Deviced::h(float)" << x << endl; }
};
void main()
{
Deviced d;
Base *pb = &d; //基类指针指向派生类
pb->f(3.14f); //覆盖
/*virtual Deviced::f(float):f是一个虚函数,派生类重写了这个虚函数
不同的范围,函数名字相同,参数相同,是基函数
派生类对象/指向派生类的指针:调用了子类的同名函数
基类对象:调用基类中的函数
*/
pb->g(3.14f); //Base::g(float)
/*不同类中,不是重载;不是virtual不是覆盖,没关系
基类指针只能访问基类g
*/
pb->h(3.14f); //Base::h(float)
Deviced *pd = &d; //派生类指针调用派生对象
pd->f(3.14f); // virtual Deviced::f(float)
pd->g(3.14f); //Deviced::g(int)
pd->h(3.14f); //Deviced::h(float),隐藏是在子类中看不到父类的函数
system("pause");
}
C++ 中重载和重写,重定义的区别
(1)重载:指的是同一可访问区内被声明的几个具有不同参数列表的同名函数,依赖于 C++函数名字的修饰 会将参数加在后⾯,可以是参数类型,个数,顺序的不同。根据参数列表决定调⽤哪个函数,重载不关⼼函数的返 回类型。
(2)重写:派生类中重新定义父类中除了函数体外完全相同的虚函数。
- 被重写的函数不能是static的,一定要是虚函数,而且其他一定要完全相同。
- 重写和被重写的函数是在不同的类当中的,重写函数的访问修饰符是可以不同的,比如virtual 中是 private 的,派⽣类中重写可以改为 public。
(3)重定义(隐藏):指的是派生类的成员函数隐藏了基类函数的非virtual成员函数。
- 在调用一个类的成员函数时候,编译器会沿着类的继承链逐步向上查找函数的定义,如果找到了就停止查找了。
- 如果一个派生类和一个基类都有同一个同名函数,而编译器最后选择了派生类的函数,我们就说这个派生类的成员函数隐藏了基类的成员函数,也就是阻止了编译器继续向上查找函数的定义。