24.c/c++程序员面试宝典-多态
多态是面向对象编程语言的3要素之一。多态允许将子类类型的指针复制给父类类型的指针,多态性在c++中是通过虚函数来实现的。c语言由于是面向过程语言,所以它不支持多态,但是可以通过结构来进行一些类似的模拟。
面试题103 什么是多态?多态的作用*****
分析:多态是面向对象的重要特性之一,它是一种行为的封装,简单的描述就是“一个接口,多种实现”,也就是一种事物所表现出的多种形态。
编写程序实际上就是一个将世界的具体事物进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来,再通过这个抽象的事物,与不同的具体事物进行对话。
对不同类的对象发出相同的消息的时候,将会有不同的行为。例如,你的老板让所有员工在9点钟开始工作。他会在9点钟的时候发出公开消息说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”。因为“员工”是一个抽象事物,只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
在面向对象编程中多态的主要作用表现为以下两点:
(1)应用程序可以不必为每一个派生类编写功能调用,而只需要对抽象基类进行处理即可。这样就大大提高程序的可复用性,精简了代码的编写量。尽量多的编写可复用代码是编写好面向对象语言程序的一个重要规则。
(2)派生类的功能可以被基类的方法或引用变量所调用,这称为向后兼容,可以在很大程度上提高可扩充性和可维护性。
多态的使用示例代码如下:
class Bird //定义抽象类
{
public:
virtual void fly() //定义虚函数
{
cout<<"Bird can fly"<<endl;
}
}
class Duck : public Bird //子类继承抽象类
{
public:
void fly //继承,派生类1
{
cout<<"Duck can`t fly"<<endl;
}
}
class Chicken : public Bird
{
public:
void fly //继承,派生类2
{
cout<<"Chicken can`t fly"<<endl;
}
}
void main()
{
Bird *birdOne =new Duck();
birdOne->fly();
Bird *birdTwo=new Chicken();
birdTwo->fly();
Bird *birdThree ;
birdThree.fly();
}
上面代码定义了一个抽象类Bird和Bird的两种子类Duck和Chicken,他们都有一个fly的方法。子类的fly方法是派生于父类的虚函数的,两个子类的方法表现出不同的功能,运行结果如下:
Duck can`t fly
Chicken can`t fly
Bird can fly
【答案】多态是面向对象编程的核心概念之一。多态技术运行将父类设置成和它的一个或更多的子对象相等。
面试题104 在c++中如何实现多态****
分析:在c++中,编程者经常指的多态是动态多态,它的实现的基础是继承机制和虚函数,通过抽象类的派生来实现多态。实现动态多态的示例代码如下:
dynamic_poly.h
#include<iostream>
class Vehicle //定义抽象类
{
public:
virtual void run() const=0;
}
class Car::public Vehicle //派生于Vehicle的具体类Car
{
public:
virtual void run() const
{
std::cout<<"run a car\n";
}
}
class Airplane:public Vehicle //派生于Vehicle的具体类Airline
{
public:
virtual void run() const
{
std::cout<<"run a airplane\n";
}
}
#include<iostream>
#include<vector>
#include "dynamic_poly.h"
//通过指针run任何Vehicle
void run_vehicle(const Vehicle* vehicle)
{
vehicle->run(); //根据Vehicle的具体类型调用对应的run()
}
int main()
{
Car car;
Airplane airplane;
run_vehicle(&car); //调用car::run()
run_vehicle(&airplane); //根据airplane的具体类型调用对应的run()
}
上面代码展示了动态多态的实现,通过定义抽象基类定义派生类方法的虚函数,客户程序可以通过指向基类Veh的指针来使用具体对象。并且可以通过继承将抽象类的虚函数定义的公共方法具体实现。上面代码中airplane和car都是派生于Vehicle,它们都有run方法,并且功能有所不同。
另外c++的多态还有静态多态,函数多态以及编程者比较少见的宏多态,静态多态通过彼此单独定义但支持共同操作的具体类来描述共同性,也就是说,必须存在必须的同名成员函数,静态多态的示例代码如下:
#include<iostream>
class Car //具体类car
{
public:
void run() const
{
std::cout<<"run a car\n";
}
};
class Airplane //具体类airplane
{
public:
void run() const;
{
std::cout<<"run a airplane\n";
}
};
#include<iostream>
#include<vector>
#include"static_poly.h"
template<typename Vehicle>
void run_vehicle(const Vehicle& vehicle)
{
vehicle.run(); //根据Vehicle的具体类型调用对应的run
}
int main()
{
Car car;
Airplane airplane;
run_vehicle(car); //调用car::run()
run_vehicle(airplane); //调用airplane::run()
}
上面代码中,Vehicle被修改后用作模板参数而不是公共基类对象,通过编译器进行处理以后,最终得到run_vehicle<car>和run_vehicl<airplane>()这两个不同的函数,这是和动态不同的。
静态多态为c++引入了泛型编织的概念。这是面向对象编织的一个重要概念,泛型编织被认为是“组件功能基于框架整体而设计”的模板编程。例如,STL就是泛型编程的典范之一。STL是一个框架,它可以提供大量的算法,容器和迭代器,而且全部以模板技术实现。
函数多态也就是编程者经常说的重载,基于不同的函数参数列表,相同名称的函数可以指向不同的函数定义。函数多态的示例代码如下:
#include<iostream>
#include<string>
int mu_add(int a,int b)
{
return a+b;
}
int my_add(int a, std::string b)
{
return a+atoi(b.c_str());
}
int main() //定义两个重载的函数
{
int i=my_add(1,2); //两个整数相加
int s=my_add(1,"2"); //一个整数加上一个字符串
std::cout<<"i="<<i<<"\n";
std:;cout<<"s="<<s<<"\n";
}
经过重载,相同名称的函数就变成了不同的函数。他们可以有不同的参数列表,并且有不同的返回值。带变量的宏可以实现一种初级形式的静态多态,这就是宏多态。宏多态的示例代码如下:
#include<iostream>
#include<string>
#define ADD(A,B) (A)+(B); //定义泛型记号,宏ADD
int main()
{
int i1(1),i2(2);
std::string s1("Hello,"),s2("world!");
int i=ADD(i1,i2); //两个整数相加
std::string s=ADD(s1,s2); //两个字符串相加
std::cout<<"i="<<i<<"\n";
std::cout<<"s="<<s<<"\n";
}
上面代码在被编译器编译时,表达式ADD(i1,i2)和ADD(s1,s2)分别被替换为两个整数相加和两字符串相加的具体表达式。整数相加也就是位求和,而字符串相加则是数据串进行连接。运行的结果如下:
1+2=3
Hello,+world!=Hello,world!
【答案】多态有动态多态,静态多态,函数多态和宏多态等。编程者常说的多态指的是多态多态,它是基于继承机制和虚函数来实现的。