首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

编程小技巧:多态原理

今天要跟大家分享的小技巧是关于多态的。多态是面向对象的程序设计最重要的一个特性。多态使得程序变得更加灵活更加抽象。那么多态究竟是什么呢?它在计算机内部到底是如何实现的呢?我们先用一句话来描述:多态就是同一种事物所表现出的多种不同的形态。比如我们在同一个类中编写两个互为重载的方法:

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的函数才能被重写。

今天的小技巧你学会了吗?

关注编程外星人

我想加入交流群

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171230G056T900?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券