C++面向对象入门(三十一)初步认识多态
继承描述的是类与类之间的层次关系, 而多态则描述的是这种继承关系以及类自生特定成员函数之间的关系来解决行为的再抽象问题
多态性的两种表现形式:
1 不同对象在收到相同信息时, 产生不同的动作, 主要通过虚函数来实现
2 同一对象在收到相同信息时却产生不同的函数调用, 主要通过函数重载来实现
多态性的两种表现形式:
1 不同对象在收到相同信息时, 产生不同的动作, 主要通过虚函数来实现
2 同一对象在收到相同信息时却产生不同的函数调用, 主要通过函数重载来实现
多态性就是同一符号或名字在不同情况下具有不同解释的现象, 即指同一函数的多种形态
C++支持两种多态性:
1 编译时的多态性
2 运行时的多态性
C++支持两种多态性:
1 编译时的多态性
2 运行时的多态性
函数联编: 函数调用在编译时或在运行时确定其链接上相应函数体的代码的过程
C++的两种联编方式
1 静态联编: 在程序编译连接阶段进行的联编. 编译器根据源代码调用固定的的函数标识符, 然后由连接器接管
这些标识符, 并利用物理地址代替, 又称为早期联编, 在程序运行之前完成的. 该联编方式支持的多态性被称作
编译时的多态性 ,调用重载函数时, 编译器可以根据调用时所使用的实参在编译时就确定应调用哪个函数.
1 静态联编: 在程序编译连接阶段进行的联编. 编译器根据源代码调用固定的的函数标识符, 然后由连接器接管
这些标识符, 并利用物理地址代替, 又称为早期联编, 在程序运行之前完成的. 该联编方式支持的多态性被称作
编译时的多态性 ,调用重载函数时, 编译器可以根据调用时所使用的实参在编译时就确定应调用哪个函数.
静态联编优点: 速度快, 开销小(传递参数, 指向函数调用, 清除栈等)
2 动态联编: 程序在运行时进行的联编, 只有向具有多态性的函数传递一个实际对象时,该函数才有可能与多种
可能的函数中的一种联系起来. 这种联编又称为晚期联编. 动态联编支持的多态性被称为运行时的多态性.
可能的函数中的一种联系起来. 这种联编又称为晚期联编. 动态联编支持的多态性被称为运行时的多态性.
动态联编的优点: 增加了编程灵活性, 问题抽象性和程序易维护性.
动态联编的确定: 函数调用速度慢(相比于静态联编)
动态联编的确定: 函数调用速度慢(相比于静态联编)
使用virtual关键字指明某个成员函数具有多态性并且使用动态联编, 此时称该函数为虚函数
语法:
virtual 返回值类型 函数名(参数列表)
{
函数体
}
语法:
virtual 返回值类型 函数名(参数列表)
{
函数体
}
代码示例:
#include<iostream> using namespace std; /* 继承描述的是类与类之间的层次关系, 而多态则描述的是这种继承关系以及类自生特定成员函数之间的关系来解决行为的再抽象问题 多态性的两种表现形式: 1 不同对象在收到相同信息时, 产生不同的动作, 主要通过虚函数来实现 2 同一对象在收到相同信息时却产生不同的函数调用, 主要通过函数重载来实现 多态性就是同一符号或名字在不同情况下具有不同解释的现象, 即指同一函数的多种形态 C++支持两种多态性: 1 编译时的多态性 2 运行时的多态性 函数联编: 函数调用在编译时或在运行时确定其链接上相应函数体的代码的过程 C++的两种联编方式 1 静态联编: 在程序编译连接阶段进行的联编. 编译器根据源代码调用固定的的函数标识符, 然后由连接器接管 这些标识符, 并利用物理地址代替, 又称为早期联编, 在程序运行之前完成的. 该联编方式支持的多态性被称作 编译时的多态性 ,调用重载函数时, 编译器可以根据调用时所使用的实参在编译时就确定应调用哪个函数. 静态联编优点: 速度快, 开销小(传递参数, 指向函数调用, 清除栈等) 2 动态联编: 程序在运行时进行的联编, 只有向具有多态性的函数传递一个实际对象时,该函数才有可能与多种 可能的函数中的一种联系起来. 这种联编又称为晚期联编. 动态联编支持的多态性被称为运行时的多态性. 动态联编的优点: 增加了编程灵活性, 问题抽象性和程序易维护性. 动态联编的确定: 函数调用速度慢(相比于静态联编) 使用virtual关键字指明某个成员函数具有多态性并且使用动态联编, 此时称该函数为虚函数 语法: virtual 返回值类型 函数名(参数列表) { 函数体 } */ class A48 { public : int a; int b; A48(); void aMultiplyB(); virtual void aAddB(); }; class B48 : public A48 { public : int a; int b; B48(); void aMultiplyB(); void aAddB(); }; void func1(A48 a) { cout << "object param:"; a.aMultiplyB(); } void func1(A48 &a, int) { cout << "reference param:"; a.aMultiplyB(); } void func1(A48*a) { cout << "pointer param:"; a->aMultiplyB(); } void func2(A48 a) { cout << "object param:"; a.aAddB(); } void func2(A48 &a, int) { cout << "reference param:"; a.aAddB(); } void func2(A48 *a) { cout << "pointer param:"; a->aAddB(); } int main() { A48 a; B48 b; func1(a); //当调用普通成员函数时, 无论传入的参数是对象, 引用还是指针类型, 据调用的是基类的成员函数 //传入B48对象给函数func1(A48), 仍调用的是A48的aMultiplyB()方法,需要使用继承时的多态性来解决 func1(b); //传入B48对象的引用 func1(b, 0); //传入B48对象的指针 func1(&b); func2(a); //当调用的函数是一个虚函数时, 传入对象类型参数, 调用基类方法, 传入引用类型参数和指针类型参数, 调用自己的方法 //传入B48对象给函数func2(A48), 仍调用的是A48的aAddB()方法,需要使用继承时的多态性来解决 func2(b); //传入B48对象的引用, 调用的是B48的aAddB() func2(b,0); //传入B48对象的指针, 调用的是B48的aAddB() func2(&b); b.aAddB(); system("pause"); } A48::A48() :a(3), b(4) { } void A48::aAddB() { cout << "A48a + b = " << a + b << endl; } void A48::aMultiplyB() { cout << "A48 a * b = " << a * b << endl; } B48::B48():A48(),a(4),b(5) { } void B48::aMultiplyB() { cout << "B48 a * b = " << a * b << endl; } void B48::aAddB() { cout << "B48 a + b = " << a + b << endl; }
路漫漫其修远兮,吾将上下而求索。