声明三个定义:
1、重载
1、作用域相同(不能再两个类中)
2、函数名相同
3、参数相同,而对返回值没有要求
2、重定义(隐藏)
1、分别位于派生类与基类
2、函数名相同
3、参数可以不同,返回值可以不同
3、重写(覆盖)
1、分别位于派生类与基类
2、函数名相同
3、参数相同
4、返回值相同(即函数原型必须相同)
5、基类函数中有virtual关键字,不能有static
6、重写函数的访问修饰符可以不同
说明:重定义不管基类是否有virtual关键字。可以说重写是重定义的一种。
一、函数重载的条件:
1、相同的作用域
2、函数名字相同
3、参数不同(包括参数个数、参数类型),但是对返回值没有要求
二、泛型编程:
1、泛型编程是基于模板实现的。模板分为函数模板和类模板。
2、函数模板
函数模板的原型:
template<typename T>
返回值 函数名(T a);
其中T表示一种类型,比如int、char、或者自定义类型。
调用方式:
函数名<T的类型>(参数列表);
举例说明:
//声明函数模板
template< typename T>
T Add(T a, T b)
{
return a + b;
}
//调用函数模板
int i = 1,j = 2;
cout<<"i + j = "<<Add<int>(i,j)<<endl;
输出结果为"i + j = 3"
说明:类型可以使用默认类型(比如上边可以写成cout<<"i + j = "<<Add(i,j)<<endl;)但是不建议使用默认类型。
3、类模板
类模板和函数模板相似,但是使用较少这里不再详细说明,感兴趣的朋友可以百度。
三、动态多态:
这是一个重点。动态多态实现的核心就是子类重写父类的虚函数(纯虚函数也是虚函数的一种)。这里分为两步讲解:1动态多态的实现(环境搭建)。2动态多态的使用(其实不能这么叫但是为了方便这里就这么叫了)。
1、实现
代码说明
//基类 base
class base{
public:
void fun1()
{
cout<<"基类方法1被调用"<<endl;
return;
}
void fun2()/* = 0;*/
{
cout<<"基类方法2被调用"<<endl;
return;
}
virtual void fun3()
{
cout<<"基类方法3被调用"<<endl;
return;
}
virtual void fun4()
{
cout<<"基类方法4被调用"<<endl;
return;
}
};
//派生类Derive
class Derive: public base
{
public:
void fun1(int i)
{
cout<<"派生类方法1被调用"<<endl;
return;
}
void fun3()
{
cout<<"派生类方法3被调用"<<endl;
return;
}
void fun5()
{
cout<<"派生类方法5被调用"<<endl;
return;
}
};
这样动态多态的环境就搭建好了。
2、使用
使用的实质是使用父类的指针指向子类的对象,然后通过指针调用方法。这里分为5种情况:1、父类中的方法不是虚函数,而且子类中重定义了这个方法(如上边的fun1)。2、父类中的方法不是虚函数,而且子类中没有重定义这个方法(如上边的fun2)。3、父类中的方法是虚函数,子类重写了这个方法(如上边的fun3)。4、父类中的方法是虚函数,而子类没有重写这个方法(如上边的fun4)。5、父类中没有改方法,而子类中有(如上边的fun5);
2.1、父类中的方法不是虚函数,而且子类中重定义了这个方法(如上边的fun1)
Derive d;
base b;
base *p = &d;
b.fun1();//调用的是base中的方法
d.fun1();//调用的是Derive中的方法
p->fun1();//调用的是base中的方法
2.2、父类中的方法不是虚函数,而且子类中没有重定义这个方法(如上边的fun2)
b.fun2();//调用的是base中的方法
d.fun2();//调用的是base中的方法
p->fun2();//调用的是base中的方法
2.3、父类中的方法是虚函数,子类重写了这个方法(如上边的fun3)
动态多态主要使用的是这种方式。
b.fun3();//调用的是base中的方法
d.fun3();//调用的是Derive中的方法
p->fun3();//调用的是Derive中的方法
2.4、父类中的方法是虚函数,而子类没有重写这个方法(如上边的fun4)
b.fun4();//调用的是base中的方法
d.fun4();//调用的是base中的方法
p->fun4();//调用的是base中的方法
2.5、父类中没有改方法,而子类中有(如上边的fun5);
b.fun5();//语法错误
d.fun5();//调用的是Derive中的方法
p->fun5();//语法错误
总结父类的指针指向派生类后通过父类的指针调用的方法。分一下几种情况
1、如果父类中的函数不是虚函数则调用的是父类中的函数
2、如果父类总的函数是虚函数则调用的是子类中的函数(如果子类没有重写这个函数则调用的仍然是父类的函数)
3、如果父类没有改函数而子类中有则父类的指针不能调用该函数。