c++多态说明

声明三个定义:

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、如果父类没有改函数而子类中有则父类的指针不能调用该函数。

 

相关文章: