新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → [转帖]深入探讨面向对象专题 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 4127 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [转帖]深入探讨面向对象专题 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     wcdxyl 帅哥哟,离线,有人找我吗?天秤座1980-10-9
      
      
      威望:4
      等级:大四(每天看1小时莱昂氏)(版主)
      文章:158
      积分:1145
      门派:IEEE.ORG.CN
      注册:2006/3/14

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给wcdxyl发送一个短消息 把wcdxyl加入好友 查看wcdxyl的个人资料 搜索wcdxyl在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看wcdxyl的博客楼主
    发贴心情 [转帖]深入探讨面向对象专题

    2.深入探讨面向对象:
    2.1“类型”的内部细节:
      有了上面的知识,我们现在就可以深入的挖掘类的内部实现了。所有的知识点我都会围绕着类与对象展开,在此之前,我希望你能够确信对以上所介绍的基本内容已完全掌握了!
      是的,面向对象的编程语言最大的特色就是可以编写自己所需的数据类型,以更好的解决问题。我想我必须要帮你搞清楚“类,对象,属性,方法它们之间的关系”!就像我前面所说的,人这个“类”是什么也做不了的,因为“人类”只是一个抽象的概念,它不是实实在在的“东西”,而这个“东西”就是所谓的对象。只有人这个“对象”才能去工作。而类呢?类是对象的描述!对象从类中产生出来!此时,对象具有类所描述的所有的属性以及方法。-------一定要理解这句话!!!
    也许你已经有些不知所措了,没关系!好好的回味一下,我再举个例子!例如电视机,电视机都有工作原理图,那么什么叫电视机呢?只要它能够实现工作原理图的所有功能的物体,我们都叫它电视机。你想想是不是这么一回事儿?可是,电视机原理图是不能工作的,也就是这个原理图不能收看节目,只有电视机这个“实体——即所谓的对象”才能收看节目,也就是说,从类生成出对象之后才算得上是真正的有意义!才能开始工作。此时,电视机拥有电视原理图所描述的所有的属性及方法!明白了吧,呵呵!
      我先前介绍过,类是属性与方法的集合。而这些属性与方法可以被声明为私有的(private),公共的(public)或是受保护(protected)的,他们描述了对类成员的访问控制。下面我分别做一下介绍:
      1. 公共的(public):把变量声明为公共类型的之后,那么就可以通过对象来直接访问,一切都是暴露无遗的!也就是说,你的信用卡密码别人也能够直接得到。
      2. 私有的(private):如果把变量声明为私有的情况就好多了,想要得到我的信用卡密码,对象必须要调用专用的方法才能够得到。
      3. 受保护的(protected):介绍继承时再讨论。
      4. 默认控制访问符(friendly)://JAVA中有而C++中没有。
    为了实现数据的封装,提高数据的安全性,我们一般会把类的属性声明为私有的,而把类的方法声明为公共的。这样,对象能够直接调用类中定义的所有方法,当对象想要修改或得到自己的属性的时候就必须要调用以定义好的专用的方法才能够实现。你想想,你会把你的信用卡密码公布出来嘛?呵呵!所以,我们提倡的是:“对象调方法,方法改属性”;
    2.2通过实例看内存分配:
      说了这么多,让我们来看一个实例吧!比如:现在我们要编写某家公司员工管理系统,你认为最合适的数据类型是什么?我认为是员工个人!但是在面向过程的语言中,这样做是不允许的,因为它只能使用语言中的内部数据类型!而员工不在这个内部数据类型之内!也许有人会说可以用C语言中的struct,好注意!毕竟它是类的基础!如果你以前是一名面C或B的程序员,请你忘掉这些,让我们一起看看如何用类来实现这一切吧!
      某家公司的员工是人类的一个特殊群体,它除了具备人类的所有特性与方法外,它还有额外的特性与方法,比如她有她的工资、信用卡密码、作息时间等等,这些特性以及工作内容,工作量等等这些方法。而在计算机中我们该如何定义这个类呢?下面我将写出它的格式,让你看看在计算机中它是张什么样子的!

    /*在此我需要再次声明的是,我用的是JAVA格式,在语法格式上它与C++大不相同!许多细节以及内部操作都有诸多区别,而在思想上确实大同小异的*/
    //employee.java
    public class employee{
    private String name; //员工姓名
    private int age; //员工年龄
    private char sex; //员工性别
    private float emolument; //员工薪水
    private boolean lunch; //员工午餐
    //……等等
    public void heater(){ //这个方法是用来加工员工的午餐
    lunch = true;
    }
    public void setName(String a){ //这个方法是修改员工的姓名
    name= a;
    }
    public String getName(){ //这个方法是得到员工的姓名
    return name;
    }
    //……等等
    }

      这样我们就定义完了我们所需要的数据类型。现在,让我们来看看它能够干什么以及怎么工作!
      我想要做的是,工作室里有一个光杆司令叫“jingwei”,我修改它的名字后对对它进行输出,看看我是怎么做的吧!
    注意:请仔细观察对象是如何调用方法的,它使用了“.”操作符!事实上是这样的,对象调用公共的属性或方法时就会使用“.”操作符。
    然而在C++中,如果定义一个同类型的指针,该指针调用此对象的方法时,就会使用“->”操作符。更详细的内容清参阅相关书籍了!

    //workstation.java
    import java.awt.Graphics;
    import java.applet.Applet;
    public class workstation extends Applet{
    private employee jingwei ; //对象的声明,此时并不分配内存!
    public void init(){
    jingwei = new employee(); /*此时创建对象会调用构造函数,稍候介绍*/
    jingwei.setName(“jw”); //设置我的名字
    }
    public void paint(Graphics g){
    g.drawString("my age is "+jingwei.getName(),10,10);//显示我的年龄
    }
    }

    输出结果是:

    my name is jw

      这串字符串是在输出窗口的x坐标轴为10 px , y坐标轴为10 px的位置。
    我现在要做的是,把上面的程序做个大解剖,让你能够看清楚它到底是怎么一回事儿!(我可不时带你去看里面的汇编,呵呵,那个我也不会:)

      首先还是来看看我们自定义的数据类型employee,在应用的时候它和int类型的数据没什么两样,一样的需要创建变量(对象),只不过前者是咱自己定义的,而后这是它内置的。Employee这个类中有许多属性,也有许多方法。而此时,我们不能直接用我们所创建出来的对象调用它的属性进行修改。因为它是private受保护类型的!我要想修改我的姓名我就要用对象调用setName()这个方法,而我想得到我的姓名就要调用getName()这个方法。我们完全是按照航线来行走的,这个航线就是“对象调方法,方法改属性”
      好的,我真的相信你已经明白了这是怎么一回事儿了!呵呵!仰起航帆,继续前行!
      
    作者: blackhailang 发布日期: 2006-1-31
    现在让我们一起来看看workstation这个类。这是个主类,和C++中的main()函数的味道差不多。其中,在JAVA中,一个文件只允许有而且必须有一个主类,这个主类用public来声明!他就跟C++中必须要有一个main()函数是一样的。
      让我们来看看这个类中的第一条语句!private employee jingwei ;这条语句的作用是声明一个employee的对象jingwei(在C++中就不用声明了)。我想要和你说的是“声明”与“定义”之间的区别。声明只是告诉计算机将要有这样的一个变量(对象),在内存中它并不为这个变量(对象)分配内存!而只有在定义的时候才会给这个变量(对象)分配内存。(需要说明一下的是init()方法是完成初始化操作的,在此处定义对象,为对象分配内存。start()方法用来启动浏览器的主线程,paint()方法来显示Apple的界面。这些是Applet程序所需的,至于Application程序就不需要了,当然了,C++中也不需要他们。关于他们的详细内容清参阅相关书籍)
      紧接着就开始定一个对象了,对jingwei这个对象进行操作才会有实际的意义。千万不要有这种想法:“试图对类进行操作!”就像前面我说的,电视机原理不能看电视一样!这是毫无意义的!看这条语句jingwei = new employee();它的意思就是定义一个employee类型的对象jingwei。此时,我想告诉你的是:“jingwei这个对想拥有了些什么”。它拥有了类所描述的所有的属性及方法。下面我一一给你列出来:

    /*所有的employee对象都拥有这些属性。每创建一个对象就会从新分配一块内存来存放相应对象的这些属性。我的意思是每个对象都有自己“独特”的一份*/
    private String name; //员工姓名
    private int age; //员工年龄
    private char sex; //员工性别
    private float emolument; //员工薪水
    private boolean lunch; //员工午餐
    /*所有的employee对象都拥有这些方法。但在内存中只有一份*/
    public void heater(){ //这个方法是用来加工员工的午餐
    lunch = true;
    }
    public void setName(String a){ //这个方法是修改员工的姓名
    name= a;
    }
    public String getName(){ //这个方法是得到员工的姓名
    return name;
    }
    /*但是,实际上在创建jingwei这个对象时计算机只给这个对象的所有的属性分配了内存,而并没有给方法分配内存。方法只有一个,是属于所有的对象的,所以无论创建了多少个对象,计算机只会为一个方法分配一块内存。*/
     我想我还是举个例子吧,不然你非晕倒不可。呵呵!
      看我这条语句“private boolean lunch;”公司不管午餐,每个员工都需要带饭。我们现在这样想,公司的空间是所有的内存容量,你的办公桌就是计算机中的内存中的一部分(每个员工都有一份,是在创建对象时分配的)。你把午饭带到了公司,放在了你的办公桌上。“午饭”占据了你的办公桌的一角(占了你自己“对象”的一块内存容量)。这份午饭只属于你自己,同样别人的也只属于她自己!所以每个员工(对象)都需要一快空间(内存)来存放自己的午餐(属性)。在计算机中也是这样的,每创建一个对象,就会在内存中从新分配一块内存来放“午餐——lunch”这个属性(对象所拥有的所有的属性)。
      计算机只会为对象的属性分配内存。因为每个对象的都不一样!就像你往公司带的午饭和我往公司带的午饭不一样是一个道理!但方法就不同了。早晨带的饭中午就凉了,你需要用微波炉来加热。微波炉可不用你带,公司就有(只占公司的一块空间),它放在了午餐桌上。你想想,微波炉属于谁的?它属于所有员工的!因为每个员工都可以用它。而不必每个员工都带一份。由此可见,每个员工(对象)都有一份午饭(属性),但所有的员工(对象)只一个微波炉(方法)。所有的员工(对象)都可以通过这个微波炉(方法)来改变自己午餐(属性)的冷热状态。殊途同归!在计算机中也就是这样,方法只有一份,供所有的对象使用!而属性是每个对象一份,因为每个对象的都不一样。别和我说你还不明白,不然我会撞墙的,呵呵:)

      2.3深入探讨函数:
      
      2.3.1构造函数、默认构造函数、 缺省构造函数
      
      对于上面的实例,它已经能完成绝大部分工作了,但它还是不完善的,还有许许多多的细节等到我们去完善!也许有的同学已经注意到了,当我创建完“jingwei”这个对象时,这个对象的所有的属性都是空的,也就是说:这个对象的姓名是未定的、年龄是未定的、性别是未定的、薪水是未定的、午餐也是未定的。而我们想把这些属性都添加上去,就还要用对象调用相应的方法,去一个个修改!天啊,这简直是太麻烦了!有没有什么好方法能够在我们创建对象的同时就完成了对属性赋值的操作呢?哦不,应该说是对属性的初始化呢?当然没问题了,这就需要所谓的构造函数!
      构造函数是类中最特殊的函数,它与析构函数的功能正好相反!
      从特征上来说:1.它是编程语言中唯一没有返回值类型的函数。
      2.它的名称与类的名称必须要完全相同。
      3.它必须被声明为公共(public)的类型
      4,可以对构造函数进行重载。
      5.它在创建对象是自动被调用。
      从功能上来说:1.它是对类中的属性进行初始化。  
      其实,对于上面的程序来说我们没有自己定义构造函数。但是,在这种情况下,系统会自动为我们定义一个“默认构造函数”。他会把数值变量自动赋值为0,把布尔行变量赋值为false等等(但在C++中,默认构造函数不初始化其成员)。如果程序员定义了构造函数,那么系统就不会再为你的程序添加一个缺默认造函数了。(在这里,我们提倡的是自己定义构造函数,而不是用系统的默认构造函数)
      还是看个实例吧!这样比较清楚一些!

      //employee.java
      
      public class employee{
      
      private String name; //员工姓名
      
      private int age; //员工年龄
      
      private char sex; //员工性别
      
      private float emolument; //员工薪水
      
      private boolean lunch; //员工午餐
      
      //……等等
      
      public employee(){ //这个就是“默认”构造函数
      
      name = “jw”; //设置员工姓名
      
      age = 20; //设置员工年龄
      
      sex = “M”; //设置员工性别
      
      emolument = 100; //设置员工薪水
      
      lunch = false; //设置员工午餐
      
      }
      
      public void heater(){ //这个方法是用来加工员工的午餐
      
      lunch = true;
      
      }
      
      //……等等
      
      };

      这样,在我们创建“jingwei”这个对象的同时,它的所有的属性也被初始化了!显然,这大大的提高了工作效率,但是,它还是不符合要求。想想看,如果我们现在创建这个类型的第二个对象的时候会发生什么事情?告诉你,除了对象的“名”(这个名称不在是对象属性中的名称,而是对象本身的名称)不一样外,其所有的“属性值”都一样!比如:现在我们创建第二个对象flashmagic,然而我会发现这个对象的所有的属性和jingwei这个对象的所有的属性完全相同。而我们只能在用对象的方法去改变着写属性了!很显然,这种方法不大好!我们需要一种方法在创建对象的时候为对象的属性赋予“我们想要的值”。
      相信你也看到了,默认构造函数就显得无能为力了。我们需要的是带参数的构造函数,在创建对象时,我们把参数传给构造函数,这样就能完成了上述的功能!口说无凭,还是来看个实例吧:

      //employee.java
      
      public class employee{
      
      private String name; //员工姓名
      
      private int age; //员工年龄
      
      private char sex; //员工性别
      
      private float emolument; //员工薪水
      
      private boolean lunch; //员工午餐
      
      //……等等
      
      public employee(String n,int a,char s,float e,boolean l){ //看这个构造函数
      
      name = n; //设置员工姓名
      
      age = a; //设置员工年龄
      
      sex = s; //设置员工性别
      
      emolument = e; //设置员工薪水
      
      lunch =l; //设置员工午餐
      
      }
      
      public void heater(){ //这个方法是用来加工员工的午餐
      
      lunch = true;
      
      }
      
      //……等等
      
      };

      这样一来,在创建对象的同时我们就可以给他赋予我们想要的值,很显然,这可就方便多了。哦,对了!还没有告诉你怎么创建呢!哈哈,往前翻几页你会看到这句话:
      jingwei = new employee();这是创建一个对象,而我们把它改成
      jingwei = new employee("jingwei",20,'M',100,false);这样一来,所有的工作都完成了,呵呵!(在创建对象的同时赋予了我们想要的“初值”)

      2.3.2重载构造函数:
      我还是先把概念给你吧,让你有个认识,随后我们在进行论述。
      在JAVA中:
      1. 函数重载是一个类中声明了多个同名的方法,但有不同的参数个数和参数类型。
      2. 函数重构是指在子类中声明与父类同名的方法,从而覆盖了父类的方法。重构解决了子类与父类的差异问题。(在讨论到继承时我会详细说明)
      在C++中:
      1. 数重载的概念一样。
      2. 重构的概念可就不一样了,C++中功能更为庞大的虚函数。更详细内容这里就不错过多介绍了!
      其实关于重载的概念你并不陌生,在编程中相信你也接触过。呵呵!让我们来举个操作符重载的例子你就会明白了,(JAVA中不支持这个功能)我们定义三个整数变量:

      int i1=2, i2=3,i3=0;
      i3 = i1 + i2;
      
      此时i3=5;加号实现了两个数相加的运算功能。然而我们现在要定义三个字符串变量:
      
      String str1=”jing”, str2=”wei”,str3=””;
      str3 = str1 + str2;

      
    作者: blackhailang 发布日期: 2006-1-31
    此时str3 = “jingwei”;加号实现了两个字符串相加的运算功能。同样是加号,既可以把两个整型的变量加在一起,也可以把两个字符串类型的变量加在一起。同一个操作符实现了不同的功能------这就是所谓的操作符重载(嘿嘿,我说你一定见过吧:)!不就好像是汉语中的一词多意一样!我需要说明一下的是,C++中的操作符重载可没有这么简单。比如,我们可以对两个自定义类型的对象进行相加的运算,进行赋值的运算。这样书写简洁明了,而且非常实用。当然,关于操作符重载的话题太多了,有兴趣再看看书吧!
      我们把操作符的话题在转到函数上来,我们一直强调的是“对象调方法”------对象其实调的是方法的“名称”。而我们现在要对方法进想重载,也就是定义多个相同名称的函数,这样计算机在调用的时候不会混淆嘛?我想应该不会的,呵呵,因为仅仅是函数名称相同,而我们在调用函数时会把参数传递给他的。既是没有参数也是一种参数传递参数的信息(信息为无参数)!然而由于参数类型、参数数量、返回值类型不同我们就可以对相同名称的函数进行区分了!目的只有一个,用简便的方法实现更多的功能。还是举个例子吧,重载构造函数!

      public class employee{
      
      public employee(String n,int a,char s,float e,boolean l){ //看这个构造函数
      
      name = n; //设置员工姓名
      
      age = a; //设置员工年龄
      
      sex = s; //设置员工性别
      
      emolument = e; //设置员工薪水
      
      lunch =l; //设置员工午餐
      
      }
      
      public employee(){ //请注意这个函数没有参数
      
      name = “jw”;
      
      age = 20;
      
      sex = ’W’;
      
      emolument = 99;
      
      lunch = true
      
      }
      
      //……等等
      
      };

      看,在一个类中有两个名称相同的函数,可我们在使用的时候系统如何知道我们调用的是那个版本的函数呢?呵呵,我刚刚说过了,可以通过函数的参数类型、参数数量、返回值类型来确定。现在我们接着试验,我们创建两个对象其中的一个调用带参数的构造函数,第二个对象调用缺省值的构造函数。我们来看看结果:
      jingwei = new employee("jingwei",20,'M',100,false);/*创建这个对象的时候调用的是带参数的构造函数*/
      
      flashmagic = new employee();//创建这个对象是调用的是却省值的构造函数
      
      而得到的结果呢?让我们一起来看一看!
      
      Jingwei这个对象中: flashmagic这个对象中:

      name jingwei name jw
     age 20 age 20
      
      sex M sex W
      
      emolument 100 emolument 99
      
      lunch false lunch true

      看,虽然是两个名称完全相同的函数,但完成了不同的工作内容。呵呵!关于函数重载我们就料到这里吧,我相信你已经有个大印象了,而更详细的内容仍需要你的努力!
      重载普通的函数与重载构造函数大同小异,不过他多了一个this指针!this一般是对当前对象的引用。这么说吧,如果涉及到两个以上的对象时就会使用this指针。每个成员函数都有一个this指针,它是一个隐藏的参数,this指针只向调用它的对象!我说过方法只有一份,而对象都有自己的属性,当对象调用方法来先是属性的时候,他怎么来判断调用的时不是自己的属性呢?这就需要this指针来大显神威了。
      关于拷贝构造函数、内联函数、虚函数、模版等欧就不做过多的讨论了,因为JAVA中好像没有这些了。不过我需要提醒你一下的是,在C++中,类内定义的函数自动转换为内联函数,而这好像与我前面提到的思想有冲突。因为内联函数的目的是减少函数调用的开销!呵呵!我也没绕出来呢!还请哪为大虾指点一二!谢!

      2.3.3 初始化与赋值
      这里我却要提醒你一下的是,初始化与赋值是完全不同的两个概念。创建一个类的时候会调用这个类的构造函数对对象的属性进行初始化。而如果以后再把这个对象赋给其他同类型的对象时可就没那么简单了。在JAVA中直接赋值就行了,因为JAVA中取消了指针,不存在指针的深拷贝与前拷贝问题。而在C++中就需要拷贝构造函数以及操作符重载了。因为JAVA中不牵扯这些东西,所以偶就不做过多介绍了。详情请参阅相关书籍吧!
      2.3.4析够函数:
      JAVA中不再支持指针了,所以你感觉不到它的重要性,因为系统会自动为你释放内存。而在C++中一切都是手动的。在构造函数中new了一个指针,在析够函数中就要delete这个指针。
      2.3.5静态:
      现在我们再来看一看“静态”是咋一回事儿!
      把一个变量或函数声明为静态的需要“static”这个关键字。声明静态的目的是“为某个类的所有对象的某个属性或方法分配单一的存储空间”。静态的数据是属于类的,不属于任何的对象。静态的数据在声明的时候系统就为他分配了内存空间,而不用等到创建对象时。举个例子来帮你更好的理解它吧。
      还是接着上面的例子。还记得刚刚我说过的员工能用微波炉热饭的事情吧。现在我们要找一个手套,毕竟想把热好的饭从微波炉里拿出来直接下手是不行的。我把手套定义成一个布尔型的变量,它有干净和脏两种状态。想想看手套是属于谁的?所有对象?不对!因为只有方法才能属于所有的对象。它是属于类的,它像微波炉那个方法一样,在内存中只有一份,所有的对象通过方法都能够修改它。而下一次修改是基于上一次修改的基础之上的!我的意思是:一个员工把手套弄脏了,下一个员工在使用的时候它还是脏的。而这个员工把手套洗干净之后,别人再用的时候它就是干净的了!就这么点事儿,明白了吧!
      关于静态函数我想就没什么可多说的了。给我的感觉就是,它也是属于类的,在定义的时候就分配的内存。调用是可以使用类名直接调用。其他的和普通成员函数没什么不同的了不过这里需要说明的一点是:在JAVA中,静态的成员函数只能修改静态的属性,而静态的属性可以被所有的成员函数修改。不过在C++中就没这么多事儿了!
      2.4继承
      继承很好理解,它的最大好处就是“代码重用”,大大提高了工作效率。举个例子你就明白了。世界上先有的黑白电视机,它有自己的工作原理。然而人们在他的基础之上开发出了彩色电视机。彩色电视机继承了黑白电视机的所有的特性与方法!因为它既能显示彩色图像也能显示黑白图像。然而它与黑白电视机又有许多区别,在工作原理上。彩色电视及多了矩阵色电路,把彩色信号分离出三种颜色(RGB),他就能显示彩色的图像了。而黑白电视机没有这块电路,即使它收到了彩色信号也显示不了彩色图像。彩色电视机是从黑白电视机中派生出来的。所以,黑白电视机是父类,彩色电视既是子类,彩色电视继承了黑白电视机所有的特性与方法。看看再计算机中它是什么样子的吧:

      //BWtv.java 父类的定义
      
      public class BWtv{
      
      private int a;
      
      public BWtv(){
      
      a=1;
      
      }
     public changeBWtv(int i){
      
      a=i;
      
      }
      
      }
      
      //Ctv.java 子类的定义
      
      class Ctv exntends BWtv{ //注意关键字“extends”
      
      private int b;
          
      public Ctv(){
        
      b=2;
      
      }
      
      public changetCv(int x){
      
      b = x;
      
      }
      
      }

      有了上面的定义,我们来看看他们都有什么数据。
      BWtv的数据包括      Ctv的数据包括
      
      private int a      private int a
      
                  private int b
      
      public changeBWtv(); public changeBWtv()
      
      public changeCtv();

      你看,子类拥有父类的所有的方法及属性。注意关键字”extends”,它的意思是继承。在C++中使用的是“:”操作符。意思是一样的。但是这里有许多问题,首先是访问权限的问题,子类的对象拥有父类的所有的属性和方法这句话。对嘛?肯定是对的!(不过JAVA的书中可不是这么说的,他说只继承非private类型的属性及方法,我觉得它这句话有错误!)可是,子类的对象不能直接访问父类的私有属性或方法,它只能通过父类的公有成员函数来访问。而此时,如果你修改了父类的属性的值。那就真的修改了。我的意思是:父类的私有属性的值会随着子类对象调用父类的公有方法进行对相应属性的修改而发生变化!(这里面存在一个域的问题,所有的修改都是在子类中进行的,修改的是子类继承的父类的属性(在子类这个域中,此时父类以拷贝到子类中了。)。而程序中定义的父类的属性不会发生任何变化(在父类的域中),)
      其次是构造函数,在创建一个子类对象时首先要调用的是父类的构造函数,然后再调用子类的构造函数,毕竟,子类的构造函数不包括父类的属性的初始化功能!(从这一点来说我的观点又是正确的“子类的对象拥有父类的所有的属性和方法”)当然了,析够函数的调用顺序正好相反!
      现在让我们来谈谈protected这个关键字吧,它的意思是:对对象来说,声明为protected的变量是私有的,而对子类父类来说,声明为protected的变量是公共的。
      现在又出现了这样的一个问题,如果我们在子类中也定义了一个int 类型的变量a,那我们在创建子类的对象的时候调用的是子类定义的还是父类定义的呢?这就涉及到数据的隐藏的问题了,我可以告诉你肯定是调用的子类的变量a。因为,子类把父类的这个同名变量给隐藏了。而如果是方法呢?这就涉及到重构的问题了,在上面我提到过“函数重构是指在子类中声明与父类同名的方法,从而覆盖了父类的方法。重构解决了子类与父类的差异问题。”这里必须要声明一下的是,在JAVA中,子类出现了对父类属性的隐藏和父类方法的覆盖后,在子类中,子类对象仅能调用子类本身的属性和方法。要调用父类的属性和方法必须要实用super这个关键子。而在C++中就不这样了。因为它有虚函数。
      虚拟函数在C++中非常好玩的事。我们可以把需要改写的函数声明为虚函数,用virtual这个关键字来声明。这样。假如如果我们CwinApp这么一个基类,它里面定义了一个成员(虚)函数为InitInstance()和另一个为(虚)函数InitApplication()。如果我从CWinApp派生一个子类为CMyWinApp并修改了InitInstance()这个成员函数。我们并没有修改InitApplication()这个成员函数。现在我们创建CMyWinApp这个类的函数theApp,我们并创建一个指针*pApp指向这个对象theApp。此时:

      pApp->InitInstance() //指针调用的是子类CMyWinApp的虚方法
      pApp->InitApplication() //指针调用的时父类CwinApp的虚方法

        因为子类并没有修改父类的方法,所以调用的是父类的虚方法。这就牵扯到虚你表的问题。碍与本篇文章的定位,这里就不讨论了!
        关于父类与子类的对象的类型转换问题是这样的,子类对象转换为父类对象时,不会出现错误。因为子类包含父类的所有的属性及方法,而父类向子类转换时就难说了,呵呵。这还会牵扯到虚拟表的问题,也不讨论了!
      JAVA中不再支持多重继承,也就是一个类从两个以上的类中继承而来,但它却多了接口的概念“interface”。这里就不做过多介绍了!
      关于抽象基类也没什么难的!他的一个大概念就是:做为许多类的父类,不定义对象,只做派生用!
    我能做得也只有这些了,如果你能明白以上的六七成,那就是对我最大的回报了,呵呵!就像刚刚开始我说的,我只是给你一个大概的思想,至于内部的实现细节,仍需要你的继续努力。关于编程语言的内容还有许多许多,实属小生个人能力有限而不能全盘照顾到。不过作为一个初学者的你来说,这些东西都是基本的。需要我提醒你一点的是,不要指望在第一、二遍的时候看懂什么!加油:)


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    主页:http://wcdxyl.blogchina.com
    MSN:wcdxyl@163.com

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2006/3/20 17:33:00
     
     GoogleAdSense天秤座1980-10-9
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/26 0:30:05

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.012ms