码迷,mamicode.com
首页 > 其他好文 > 详细

面向对象多态简析

时间:2015-05-24 21:39:36      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:

C#&C++多态问题简析

在学习C#面向对象时,对封装和继承基本上还是理解的,但是碰到多态,基本上就是记住了个父类引用指向子类对象,在很长时间内也是一直比较困惑。学习c++时,基本上算是有了一定了解。下面结合代码解释多态问题

首先是c#代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace DuoTai

{

 

    class Father

    {

        public void FatherSayHello()

        {

            Console.WriteLine("Father");

        }

    }

 

    class Son1:Father

    {

        public void Son1SayHello()

        {

            Console.WriteLine("Son1");

        }

    }

 

    class Son2 : Father

    {

        public void Son2SayHello()

        {

            Console.WriteLine("Son2");

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            Father f = new Son1();

            //注1:f引用对象无法访问Son的函数SonSayHello

            f.FatherSayHello();

 

            //注2:子类引用可以调自己及父类的函数

            Son1 s1 = f as Son1;

            s1.Son1SayHello();

            s1.FatherSayHello();

 

            f = new Son2();

            Son2 s2 = f as Son2;

            s2.Son2SayHello();

 

            ////注3:下面问题会抛出异常

            //Father ff = new Father();

            //Son1 s11 = ff as Son1;

            //s11.FatherSayHello();

            //s11.Son1SayHello();

            Console.Read();

        }

    }

}

运行结果想必大家还是很清楚的。

                       

本人程序员一枚,没做过什么高大上的程序设计,但看这个多态案例,貌似没什么高深之处。就是声明一个父类引用,可以指向不同的子类实例。有一个疑问,子类引用为什么不能指向父类实例呢?不兜圈子,直接分析对象实例化过程来分析,上图:

 

很简单,当我们new一个子类对象时,首先会先new一个父类对象,可以这么理解,子类对象包含一个父类对象。

不管是子类引用还是父类引用,我们都可以理解为指针,存储在栈上,值为指向的堆上的对象内存地址。既然可以理解为指针,指针的类型决定解析方式。如上图,子类对象可以搜索到父类及子类的函数,而父类对象只能搜索到自己的函数,这样,上面C#代码中注1和注2也就很容易理解了。(※这里我们只是讨论多态问题,作用域问题,不再考虑范围之内,至于父类的private函数问题什么的,也就不要吐槽了。)

说到这里,子类引用为什么不能指向父类实例也就很明白了,假设我们声明子类引用,当我们调用自己的SonSayHello()方法时,但是父类实例并没有这个方法,我们就无法调用了。

上面的分析目前还只是我的一面之词,我需要用c++代码加以佐证,要不然别人该说我瞎扯了,废话不多说,直接上c++代码及运行结果

1.验证创建子类对象时会先创建父类对象,下图是运行结果。

 

2.用c++代码解释面向对象,以及c++面向对象与c#的不通

#define  _CRT_SECURE_NO_WARNINGS

#include <iostream>

#include<string>

 

using namespace std;

 

class Father

{

public:

         Father();

         ~Father();

public:

         void FatherSayHello();

 

};

 

Father::Father()

{

         cout << "Father Created" << endl;

}

 

Father::~Father()

{

         cout << "Father Deleted" << endl;

}

 

void Father::FatherSayHello()

{

         cout << "Father" << endl;

}

 

class Son1:public Father

{

public:

         Son1();

         ~Son1();

 

public:

         void Son1SayHello();

         void Son1SayName();

public :

                   char * name;

 

};

 

Son1::Son1()

{

         cout << "Son1 Created" << endl;

}

 

Son1::~Son1()

{

         cout << "Son1 Deleted" << endl;

}

 

void Son1::Son1SayHello()

{

         cout << "Son1" << endl;

}

 

void Son1::Son1SayName()

{

         cout << this->name << endl;

}

void main()

{

         //验证创建子类对象时会同时创建父类对象

         Son1 *ps1 = new Son1;

         delete ps1;

 

         //父类指针指向子类对象

         Father *pf1 = new Son1;

         delete pf1;

 

         //子类指针不能指向父类对象

         //Son1 *ps2 = new Father;//报错,原因同上面对C#面向对象的分析

 

         //通过指针转换实现子类指针指向父类对象,这个不同于C#,

         //Son1的Son1SayHello()调用成功的原因是类成员函数是存在共享区域的,成员变量是存在私有区域的

         Father *pf2 = new Father;

         Son1 *ps2 = reinterpret_cast<Son1 *>(pf2);

         ps2->FatherSayHello();

         ps2->Son1SayHello();

 

         //加上这一段代码,程序会抛出异常,因为我们在调用Son1SayName()的时候

         //要同时调用类的成员变量

         //ps2->Son1SayName();

 

         //为对函数共享,成员变量私有佐证,请看下面代码

         //给对象指针复制nullptr后,函数仍然可以正常调用

         Son1 * ps3 = nullptr;

         ps3->Son1SayHello();

        

         cin.get();

}

 

 

以上是个人分析总结,如有错误,敬请指正。

面向对象多态简析

标签:

原文地址:http://www.cnblogs.com/aaron-song/p/4526437.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!