重载:
重载在之前已经讲过,这里不在赘述详细的
link.
在同一个作用域下,函数名相同,参数列表不同即构成重载
条件:
必须在同一个作用域(类)下
函数名相同
参数列表不同: 参数类型和参数的个数不一样 对于指针和引用常属性不一样也构造重载
与返回值类型无关
与函数是否是虚函数无关
在编译时,根据调用时传递的实参类型和个数来绑定调用的函数,静态绑定
覆盖(重写):
说起覆盖先说一下虚函数
在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数,用法格式为:virtual 函数返回类型 函数名(参数表) {函数体};实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。
如果使用了virtual关键字,程序将根据引用或指针指向的 对 象 类 型 来选择方法,否则使用引用类型或指针类型来选择方法。
子类重写父类同型的虚函数
条件:
分布在父子类中
函数名相同
参数列表必须相同:参数类型和个数必须相同 函数的常属性必须相同 参数是指针和引用 常属性也必须相同
与返回值类型有关 如果不是类类型指针或者类类型引用,必须完全一致,否则可以有父子关系
基类必须是虚函数 重写的版本也一定是虚函数
在运行时,根据指针所指向的目标类型 或者 根据引用所引用的目标类型,来决定调用哪个版本的方法
动态绑定 在运行时才决定调用哪个函数
#include <iostream>
using namespace std;
class Shape{
private:
double x;
double y;
public:
Shape(double x=0,double y=0):x(x),y(y){}
virtual double len(){
cout << "shape::len()" << endl;
return 0.0;
}
virtual double area(){
cout << "shape::area()" << endl;
}
void draw(){
cout << "shape::draw() position:<" << x << "," << y << ")" << endl;
}
static Shape* maxArea(Shape* srr[],size_t size){
Shape *pm = srr[0];
for(int i=1;i<size;i++){
cout << "-------------" << endl;
if(srr[i]->area() > pm->area()){
pm = srr[i];
}
}
return pm;
}
};
class Rect:public Shape{
private:
double l;
double w;
public:
Rect(double x,double y,double l,double w):Shape(x,y),l(l),w(w){
}
double len(){
cout << "Rect::len()" << endl;
return 2*(l+w);
}
double area(){
cout << "Rect::area()" << endl;
return l*w;
}
};
class Circ:public Shape{
private:
double r;
static double PI;
public:
Circ(double x,double y,double r):Shape(x,y),r(r){
}
double len(){
cout << "Circ::len()" << endl;
return PI*2*r;
}
double area(){
cout << "Circ::area()" << endl;
return PI*r*r;
}
};
double Circ::PI = 3.14159;
int main(){
Rect r(0,0,2,4);
Circ c(0,0,3);
cout << r.len() << endl;
cout << c.len() << endl;
cout << r.area() << endl;
cout << c.area() << endl;
Shape* ps = &r;
ps->len();
ps->area();
ps = &c;
ps->len();
ps->area();
Shape& rs = r;
rs.len();
rs.area();
Shape& rc = c;
rc.len();
rc.area();
Shape* arr[5] = {
new Rect(0,0,4,1),new Circ(0,0,3),new Rect(0,0,3,3),
new Circ(0,0,2),
new Rect(0,0,2.5,4)
};
ps = Shape::maxArea(arr,5);
cout << ps->area() << endl;
return 0;
}
隐藏:
子类隐藏父类同名的标识符(只讨论函数)
条件:
分布在父子类中
函数名相同
如果参数不同,不管是否有virtual关键字,都构成隐藏
如果参数一致,基类函数没有virtual关键字,构成隐藏,否则构成覆盖
#include <iostream>
using namespace std;
class A{};
class B:public A{};
class F{
public:
void f1(){
cout << "F::f1()" << endl;
}
void f1(int x){
cout << "F::f1(int)" << endl;
}
virtual void f2(){
cout << "F::f2()" << endl;
}
void f2(int x){
cout << "F::f2()" << endl;
}
virtual int f3(){
}
int f4(){
}
void f5()const{
cout << "F::f5()const" << endl;
}
virtual void f6(){
cout << "F::f6()" << endl;
}
virtual void f7(){
cout << "F::f7()" << endl;
}
private:
virtual void f8(){//子类不可见 子类依然可以覆盖
cout << "F::f8()" << endl;
}
public:
void bar(F *pf){
pf->f8();//如果f8没有被覆盖 一定是调用父类的
}
virtual A f9(){
return A();
}
virtual A* f10(){
return new A();
}
virtual A& f11(A& a){
cout << "F::f11" << endl;
return a;
}
virtual void f12(int x){
cout << "F::f12" << endl;
}
};
class S:public F{
public:
void f1(){//隐藏 f1() f1(int x)
cout << "S::f1()" << endl;
}
void f2(){//重写
cout << "S::f2()" << endl;
}
/*
void f3(){//隐藏 覆盖 父类中的f3 虚函数+参数列表一致 覆盖 要求返回值类型
}
*/
void f3(int){
}
virtual void f4(){//隐藏
}
void f5(){
cout << "S::f5()" << endl;
}
void f6()const{//常属性不一致 不会构成覆盖
cout << "S::f6()" << endl;
}
private:
virtual void f7(){
cout << "S::f7()" << endl;
}
public:
void f8(){
cout << "S::f8()" << endl;
}
/*
B f9(){//函数名一样 参数列表一样 基类函数有virtual 返回值类型有要求
return B();
}
*/
B* f10(){
return new B();
}
virtual B& f11(B& b){//隐藏
cout << "S::f11(B& b)" << endl;
return b;
}
virtual B& f11(A& a){//覆盖
cout << "S::f11(A& a)" << endl;
return static_cast<B&>(a);
}
void f12(const int x){
cout << "S::f12" << endl;
}
};
int main(){
S s;
s.f1();
s.F::f1();//通过显示的方式 访问 被隐藏的标识符
s.F::f1(100);
cout << "--------" << endl;
s.f2();//重写
s.F::f2();//被重写的方法也可以 显示 调用
F *pf = &s;
pf->f1(); //父类
pf->f2(); //子类
s.F::f2(100);//被子类同名的f2隐藏了
s.f5();
const S s1;
//s1.f5();
s.f6();
pf->f6();
pf->f7();//调用到了子类private方法
//s.f7();
//pf->f8();
s.f8();
pf->bar(pf);
A a; B b;
pf->f11(a);
s.f11(b);
pf->f11(b);
s.f12(1);
pf->f12(1);
return 0;
}