今天要跟大家分享的小技巧是关于多态的。多态是面向对象的程序设计最重要的一个特性。多态使得程序变得更加灵活更加抽象。那么多态究竟是什么呢?它在计算机内部到底是如何实现的呢?我们先用一句话来描述:多态就是同一种事物所表现出的多种不同的形态。比如我们在同一个类中编写两个互为重载的方法:
class A
{
public:
int max(int a, int b);
int max(float a, float b, float c);
};
在使用这个类的对象时,它对外暴露的调用方法都是max(),而它对外所表现出来的形态也是不一样的,给它传入2个参数时,它返回这2个数中较大的那一个,而给它传递3个参数,则返回这3个数中较大的那一个。这就是我们所说的同一个事物(至少对外表现出来的是同一个事物max()函数)在不同情况下(在传入2个参数和3个参数时)所表现出多种不同的形态(计算2个数的较大值和3个数的较大值)。
类的方法重载是多态中最简单的形式,理解起来也比较简单,接下来我们再来看看类与对象在继承机制中所表现出来的多态形式。我们来看这样的3个类:
这里,类A中的成员变量int i是protected它会被继承到B类和C类当中,A类中还有一个成员方法virtual void func()这是一个虚函数,它会被B类和C类重写。这3个类的代码实现如下:
class A
{
public:
A(int age = 0) :
i(age)
{
}
virtual ~A()
{
}
virtual void func()
{
cout
}
protected:
int i;
};
class B: public A
{
public:
B(int age = 0)
{
this->i = age;
}
virtual ~B()
{
}
virtual void func()
{
cout
}
};
class C: public A
{
public:
C(int age = 0)
{
this->i = age;
}
virtual ~C()
{
}
virtual void func()
{
cout
}
};
int main(void)
{
A* a0 = new A(20);
A* a1 = new B(21);
A* a2 = new C(22);
a0->func();
a1->func();
a2->func();
delete (a2);
delete (a1);
delete (a0);
return 0;
}
我们定义了3个A类的对象指针a0、a1、a2。在执行这3个指针所指向的对象的方法func时,它们对外的调用方式都是相同的,然而这3个方法所表现出来的形态却是不同的,这也就是我们所说的多态:
调用的3个方法完全相同
a0->func();
a1->func();
a2->func();
输出结果为:
My name is A. I'm 20 years old.
My name is B. I'm 21 years old.
My name is C. I'm 22 years old.
事实上,虽然a0、a1、a2的类型都是类A的指针类型,但它们在内存中的真正形态是不同的,我们再来仔细看看a0、a1、a2这3个变量定义的代码:
A* a0 = new A(20);
A* a1 = new B(21);
A* a2 = new C(22);
值得注意的是它们的类型都是 A* 但是它们在申请内存空间时(也就是使用new修饰符创建对象时)这3个相同类型的指针指向了3个不同类型的对象,分别为A类的对象、B类的对象和C类的对象,它们在内存中实际的内容是这样的:
也就是说同样的A类的3个指针a0、a1和a2它们所指向的实际对象不同,我们在创建一个对象时(使用new修饰符时)计算机已经在内存中创建了这个对象应该所具有的内存空间,其中也包含了由父类所继承下来的属性,而对外表现同一种类型的对象指针a0、a1和a2在执行对象操作时,实际上就是在执行这3个不同对象,所以会表现出3种不同的形态。
这里还有一个需要注意的细节:我们使用了virtual修饰符来修饰成员方法void func(),如果不使用virtual修饰修饰成员方法,那么这里的多态机制将不会起作用,因为C++规定使用一个基类的指针来调用子类的成员函数时,如果这个函数是虚函数(被virtual修饰)则调用的函数是子类的函数,如果这个函数不是虚函数则调用的是基类的函数。这也就是C++中的动态联编机制。C++与Java是采用了相反的机制来控制函数的重写:
C++ 规定:指定了virtual的函数才能被重写,没有被指定virtual的函数不能被重写;
Java规定:指定了final的函数不能被重写,没有被指定final的函数才能被重写。
今天的小技巧你学会了吗?
关注编程外星人
我想加入交流群
领取专属 10元无门槛券
私享最新 技术干货