精华内容
下载资源
问答
  • 计算机代码的可扩充性和可维护性? 多态的作用如何理解?
  • 8.1面向对象继承

    2019-10-12 17:12:05
    继承性是指扩充一个已有的的功能,基本语法。 class 子类extends 父类{} 在继承结构中,很多情况下会把子类称为派生类,把父类称为超类(SupperClass)。 范例:继承基本实现 public class Person { private ...

    8.1.1继承的引出

    提高程序代码的可重用性

    8.1.2类继承定义

    继承性是指扩充一个已有的的功能,基本语法。

    class 子类extends 父类{}
    

    在继承结构中,很多情况下会把子类称为派生类,把父类称为超类(SupperClass)。
    范例:继承基本实现

    public class Person {
           private String name;
           private int age;
           public void setNane(String name) {
        	   this.name=name;
           }
           public String getName() {
        	   return name;
           }
           public void setAge(int age) {
        	   this.age=age;
           }
           public int getAge() {
        	   return age;
           }
           public Person(){}
           public Person(String name,int age) {
        	   this.name=name;
        	   this.age=age;
           }
    }
    ----------------------------------------------------------
    public class Student extends Person {
           //在子类中定义任何构造
    }
    
    ------------------------------------------------------------------
    
    public class JavaDemo01 {
           public static void main(String[] args) {
    		Student stu=new Student();
    		stu.setNane("张三");
    		stu.setAge(22);
    		System.out.println("姓名:"+stu.getName()+"  年龄:"+stu.getAge());
    	}
    }
    
    
    姓名:张三  年龄:22
    

    子类可以继续重用父类中定义的属性和方法,同时可以根据子类功能的需要进行结构扩充。所以子类往往要比父类描述的范围更小。
    范例:在子类的中扩充父类的功能

    public class Person {
           private String name;
           private int age;
           public void setNane(String name) {
        	   this.name=name;
           }
           public String getName() {
        	   return name;
           }
           public void setAge(int age) {
        	   this.age=age;
           }
           public int getAge() {
        	   return age;
           }
           public Person(){}
           public Person(String name,int age) {
        	   this.name=name;
        	   this.age=age;
           }
    }
    
    -------------------------------------------
    public class Student extends Person {
           private String school;//扩充属性
           public void setSchool(String school) {  //扩充的方法
        	   this.school=school;
           }
           public String getSchool() {
        	   return this.school;
           }
           
    }
    -----------------------------------------------------------
    public class JavaDemo01 {
           public static void main(String[] args) {
    		Student stu=new Student();
    		stu.setNane("张三");
    		stu.setAge(22);
    		stu.setSchool("西安文理学院");
    		System.out.println("姓名:"+stu.getName()+"  年龄:"+stu.getAge()+"  学校:"+stu.getSchool());
    	}
    }
    
    
    姓名:张三  年龄:22  学校:西安文理学院
    
    

    8.1.3子类对象实例化流程

    进行子类对象实例化之前往往会默认调用父类中的无参构造方法,为父类对象实例化(属性初始化)而后再进行子类构造调用,为子类对象实例化(属性初始化)
    范例:子类对象实例化,观察无参构造调用

    public class Extends162a {
    	  public Extends162a() {    //父类无参构造
    		  System.out.println("【父类】调用父类构造实例化对象");
    	  }
    }
    
    public class Extends162b extends Extends162a{
    	public Extends162b() {
    		System.out.println("【子类】调用子类构造实例化对象");
    	}
    }
    
    
    public class Extends162c {
         public static void main(String[] args) {
        	 Extends162b a=new Extends162b();     //实例化子类对象
        	 
    	}
    }
    
    
    【父类】调用父类构造实例化对象
    【子类】调用子类构造实例化对象
    

    本程序在实例化子类时只调用了子类构造,而通过执行结果可以发现,父类构造会被默认调用,执行完毕才会调用子类构造,结论:子类对象实例化前一定会实例化父类对象,实际上这个时候就相当于子类的构造方法里面隐含了一个super()的形式。
    范例:观察子类构造
    子类中的super()作用表示在子类中明确调用父类的无参构造,如果不写也默认会调用父类构造,对于super()构造调用的语句只能够在子类的构造方法中定义,并且放在子类构造的首行。
    如果父类没有提供无参构造方法时,可以通过“ super(参数,…) ”的形式调用指定参数的构造方法。
    范例:明确调用父类指定构造方法

    public class Person {
           private String name;
           private int age;
           public void setNane(String name) {
        	   this.name=name;
           }
           public String getName() {
        	   return name;
           }
           public void setAge(int age) {
        	   this.age=age;
           }
           public int getAge() {
        	   return age;
           }
           public Person(){}
           public Person(String name,int age) {
        	   this.name=name;
        	   this.age=age;
           }
    }
    
    public class Student extends Person {
           private String school;//扩充属性
           public void setSchool(String school) {  //扩充的方法
        	   this.school=school;
           }
           public String getSchool() {
        	   return this.school;
           }
           public Student(String name,int age,String school){
        	   super(name,age);
        	   this.school=school;
           }
           
    }
    
    public class JavaDemo01 {
           public static void main(String[] args) {
    		Student stu=new Student("李四",21,"北京大学");
    		System.out.println(stu);
    		}
    		}
    

    本程序父类不在明确提供无参构造方法,这样在子类构造方法中就必须通过super()明确指明要调用的父类构造,并且该语句必须放在子类构造方法的首行。
    提问:有没有不让子类去调用父类构造的可能性
    回答:没有

    展开全文
  • 多态什么叫多态多态: 允许不同类对象对同一消息做出响应。即同一消息可以根据发送对象不同而采用多种不同行为方式。...可扩充性: 多态对代码具有可扩充性。增加新子类不影响已存在类多态性、继承性,

    多态

    什么叫多态

    多态: 指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)换句话说,猫和狗都是动物,但它们的叫声不一样,所以猫和狗是动物的多态.

    多态的好处

    • 可替换性: 多态对已存在代码具有可替换性。例如:动物会吃东西,但如果是猫会吃鱼,如果是狗会吃肉.
    • 可扩充性: 多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。在实现猫、狗实现多态的基础上,添加老鼠这个新类不会影响猫,狗原有类
    • 接口性: 多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
    • 灵活性: 它在应用中体现了灵活多样的操作,提高了使用效率。
    • 简化性: 多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

    实现多态需要三个条件

    • 继承
    • 方法的覆盖
    • 父类引用指向子类对象

    简单实例:

    父类:

    public class Animal {
    
        private int age;
    
        private String voice;
    
        public String getVoice() {
            return voice;
        }
    
        public void setVoice(String voice) {
            this.voice = voice;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String call(){
            return "我今年"+age+"岁了"+"我是这样叫的"+voice;
        }
    
    }

    子类:

    public class Cat extends Animal {
    
        public Cat cat;
    
        public Cat() {
    
            cat = new Cat();
            cat.setAge(2);
            cat.setVoice("喵喵喵");
        }
          @Override
        public String call() {
            return "我是只猫,我今年"+cat.getAge()+"岁了"+"我是这样叫的"+cat.getVoice();
        }
    }
    public class Dog extends Animal {
    
        public Dog dog;
    
        public Dog() {
            dog = new Dog();
            dog.setAge(5);
            dog.setVoice("汪汪汪");
        }
        @Override
        public String call() {
            return "我是条狗,我今年"+dog.getAge()+"岁了"+"我是这样叫的"+dog.getVoice();
        }
    }

    测试类:

    
    public class Test {
    
        private Test test;
    
        public String animalCall(Animal animal){
            return animal.call();
        }
    
        public Test() {
            test = new Test();
            test.animalCall(new Cat());
            test.animalCall(new Dog());
            test.animalCall(new Animal());
        }
    }

    我们看到例子中,我们实现了继承,方法的覆盖以及父类引用指向子类对象这三个条件,所以我们实现了多态特性.

    展开全文
  • 其中,安全状态是指智能卡在当前所处一种状态,这种状态是在智能卡进行完复位应答或者是在它处理完某命令之后得到。事实上,我们完全可以认为智能卡在整个工作过程中始终都是处在这样或是那样一种状态之中,...
  • C++程序设计语言(特别版)--源代码

    热门讨论 2012-04-23 07:33:51
    9.2.4 与非c++代码的连接 182 9.2.5 连接与指向函数的指针 184 9.3 使用头文件 184 9.3.1 单一头文件 184 9.3.2 多个头文件 187 9.3.3 包含保护符 191 9.4 程序 192 9.4.1 非局部变量的初始化 192 9.5 忠告 ...
  • 9.2.4 与非c++代码的连接 182 9.2.5 连接与指向函数的指针 184 9.3 使用头文件 184 9.3.1 单一头文件 184 9.3.2 多个头文件 187 9.3.3 包含保护符 191 9.4 程序 192 9.4.1 非局部变量的初始化 192 9.5 忠告 ...
  • 多态与虚函数

    千次阅读 2009-11-12 08:02:00
    多态性概念:在面向对象的概念中,多态性是指不同对象接收到相同消息时,根据对象类的... 多态性提供了把接口与实现分开的另一种方法,提高了代码的组织性和可读性,更重要的是提高了软件的可扩充性。一. 重载函数1. 在

    多态性概念:

    在面向对象的概念中,多态性是指不同对象接收到相同消息时,根据对象类的不同产生不同的动作。多态性提供了同一个接口可以用多种方法进行调用的机制,从而可以通过相同的接口访问不同的函数。具体地说,就是同一个函数名称,作用在不同的对象上将产生不同的操作。

        多态性提供了把接口与实现分开的另一种方法,提高了代码的组织性和可读性,更重要的是提高了软件的可扩充性。


    一. 重载函数
    1. 在C++语言中,编译程序选择相应的重载函数版本时函数返回值类型是不起作用的。不能仅靠函数的返回值来区别重载函数,必须从形式参数上区别开来。例如:
    void print(int a);
    void print(int a,int b);
    int print(float a[]);
    这三个函数是重载函数,因为C++编译程序可以从形式参数上将它们区别开来。

    但是:
    int f(int a);
    double f(int a);
    不能进行重载,会发生编译错误。

     

    2. 函数重载的二义性(ambiguity):
      (1). 是指C++语言的编译程序无法在多个重载函数中选择正确的函数进行调用。这些二义性错误是致命的,因而编译程序将无法生成目标代码。
    函数重载的二义性主要源于C++语言的隐式类型转换与默认参数.


      (2). 在重载函数中使用默认参数也可能造成二义性

    3. 析构函数不能进行重载,因为析构函数本来就是无参数的,无返回类型的。

     

    /* 例1:test1.cpp   */
    /* IDE环境: Dev-C++ 4.9.9.2 */
    /* 重载函数举例 */

    #include <stdio.h>
    class base
    {
        public:
               //构造函数重载
               base():i(0){ };
               base(int x) { i = 10; }
               //base (int y){ j = 20; } // compile error: F:/devcpptest/devcpptest/test1.cpp `base::base(int)' and `base::base(int)' cannot be overloaded
                                           //形式与上一个一样。
               base(int x,int y) { i = x; j = y; }
              
              
               int get_i(){ return i; }
              
               //其它函数重载:
               void  display(){ printf(" base::display_i, i = %d, j = %d /n", i, j); } 
               void  display(int type)
               {
                     if (type)
                        printf(" base::display, i = %d/n", i);
                     else
                         printf(" base::display, j = %d /n", j);
               }
              
               float abs(float x)
               {
                   return (x>0?x:-x);
               }
               double abs(double x)
               {
                   return (x>0?x:-x);
               }

               //析构函数不能重载:
               ~base(){};
               //~base(int type) { i = type; } //compile error: F:/devcpptest/devcpptest/test1.cpp `base::~base()' and `base::~base()' cannot be overloaded
              
        private:
                int i;
                int j;
    };


    int main()
    {
        base b;
        printf("abs(1.78) = %f /n", b.abs(1.78)) ; // OK, 调用abs(double)
        //printf("abs(-7) = %f /n", b.abs(-7));    // compile error,编译程序无法确定调用哪一个abs()函数

        while(1);
    }

     

    二. 虚函数

    虚函数是重载的另一种形式,实现的是动态的重载,即函数调用与函数体之间的联系是在运行时才建立,也就是动态联编。
    在基类用virtual声明的成员函数即为虚函数。

    1. 静态联编与动态联编
       (1)静态联编:是指联编工作出现在编译连接阶段,这种联编过程是在程序开始运行之前完成的。在编译时所进行的这种联编又称静态绑定。
            在编译时就解决了程序中的操作调用与执行该操作代码间的关系,确定这种关系又称为绑定,在编译时绑定又称静态聚束。
       (2)动态联编:编译程序在编译阶段并不能确切知道将要调用的函数,只有在程序执行时才能确定将要调用的函数,
            为此要确切知道该调用的函数,要求联编工作要在程序运行时进行,这种在程序运行时进行的联编工作被称为动态联编,或称动态绑定。
            动态联编实际上是进行动态识别。
       (3)比较:

     

    程序中的形式

    聚束方式

    函数原型

    决策依据

    特点

    重载函数

    静态聚束

    不同

    参数数目及类型

    高效

    虚函数

    动态聚束

    相同

    运行时指针的指向或引用

    高效灵活,抽象性,可扩充性

     


      
      
    2. 虚函数的概念
       虚函数是在基类中冠以关键字 virtual 的成员函数。它是动态联编的基础。虚函数是成员函数,而且是非static的成员函数。
       它提供了一种接口界面,并且可以在一个或多个派生类中被重定义。
       一个虚函数是属于它所在的类层次结构的,而不是只属于某一个类。
    3. 动态联编与虚函数
       派生类中对基类的虚函数进行替换时,要求派生类中说明的虚函数与基类中的被替换的虚函数之间满足如下条件:
    (1)与基类的虚函数有相同的参数个数;
    (2)其参数的类型与基类的虚函数的对应参数类型相同;
    (3)其返回值或者与基类虚函数的相同,或者都返回指针或引用,
         并且派生类虚函数所返回的指针或引用的基类型是基类中被替换的虚函数所返回的指针或引用的基类型的子类型。
    (4)在派生类对基类中声明为虚函数进行重新定义时,关键字virtual也可以不用写,即 对于
        class Point {
        private:
            flat x,y;
        public:
            virtual float area() // 虚函数
            {
                return 0.0;
            }/
        };
        const float PI = 3.141593;
        class Circle: public Point {
        private:
            float radius;
        public:
            virtual float area()
            {
                return PI*radius*radius;
            }
        };
        派生类类中的virtual float area() 也可以写成下面的形式:
        float area()。

     

    4. 虚函数的限制

    (1)在类体系中访问一个虚函数时,应使用指向基类类型的指针或对基类类型的引用,以满足运行时多态性的要求。
    (2)在派生类中重新定义虚函数时,必须保证该函数的值和参数与基类中的说明完全一致,否则就属于重载(参数不同)或是一个错误(返回值不同)。
    (3)若在派生类中没有重新定义虚函数,则该类的对象将使用其基类中的虚函数代码。
    (4)虚函数必须是类的一个成员函数,不能是友元,但它可以是另一个类的友元。
    (5)析构函数可以是virtual的虚函数,但构造函数则不得是虚函数。
    (6)一个类的虚函数仅对派生类中重定义的函数起作用,对其他函数没有影响。

     

    5. 虚函数与重载函数的比较
    (1)重载函数要求函数有相同的返回值类型和函数名称,并有不同的参数序列;而虚函数则要求这三项(函数名、返回值类型和参数序列)完全相同。
    (2)重载函数可以是成员函数或友元函数,而虚函数只能是成员函数。
    (3)重载函数的调用是以所传递参数序列的差别作为调用不同函数的依据;虚函数是根据对象的不同去调用不同类的虚函数。
    (4)虚函数在运行时表现出多态功能,这是C++的精髓;而重载函数则在编译时表现出多态性。

     

    6. 虚函数的访问:
    (1)用基指针访问与用对象名访问;
         虚函数被指向基类的指针(或引用)调用时,C++对其进行动态聚束,向实际的对象传递消息。
         但是,通过一个对象名访问虚函数时,C++系统将采用静态聚束。
         例如,对于上面的Point 和 Circle 类,
         Point *pp;
         Circle c;
         pp = &c;
         pp->area(); //调用的是Circle的area
         调用的是Circle的area;
         而,
         Circle c;
         c.area();            // 调用的是本类Circle的area。
         c.Point::area();     // 调用的是父类Point的area,采用作用域运算符来指定调用父类的方法。
         c.Circle::area();    // 调用的是本类Circle的area。
        
        

    (2)由类的成员函数访问该类层次中的的虚函数,要使用this指针;例如,

    /* 例2:test2.cpp   */
    /* IDE环境: Dev-C++ 4.9.9.2 */
    /* 虚函数举例 */


          #include <stdio.h>
         
          class A {
                public:
                       virtual void vir_func1() {
                           printf(" v1 is called in A./n");
                           a1();
                       }
                       virtual void vir_func2() {
                           printf(" v2 is called in A./n");
                       }
                       void a1() {
                           printf(" a1 is called in A./n");
                           vir_func2();  // 等价于 this->vir_func2()
                       }
          };
         
          class B: public A {
                public:
                      
                       virtual void vir_func2() {
                           printf(" v2 is called in B./n");
                       }
                       void b1() {
                           printf(" b1 is called in B./n");
                           vir_func2();
                       }
          };
          int main()
          {
              A a;
              a.vir_func1();
              printf(" OK./n");
             
              B b;
              b.vir_func1();
             
              while(1);
              return 0;
          }
          /*
          result:
                v1 is called in A.
                a1 is called in A.
                v2 is called in A.
                OK.
                v1 is called in A.
                a1 is called in A.
                v2 is called in B.
               
          */

        
    (3)用构造函数和析构函数访问:
         这两个函数访问虚函数时,C++采用静态聚束。例如,

    /* 例3:test3.cpp   */
    /* IDE环境: Dev-C++ 4.9.9.2 */
    /* 构造函数访问虚函数举例 */
          #include <stdio.h>
         
          class A {
                public:
                       A() { };
                       virtual void vir_func1() {
                           printf(" v1 is called in A./n");
                       }
          };
         
          class B: public A {
                public:
                       B() {
                           printf(" call v1 in B./n");
                           vir_func1(); //  调用本类中定义的虚函数
                       }
                       virtual void vir_func1() {
                           printf(" v1 is called in B./n");
                       }
          };
         
          class C: public B {
                public:
                       C() {
                           printf(" call v1 in C./n");
                           A::vir_func1();  // 调用基类中定义的虚函数
                       }
                       void vir_func1() {
                           printf(" v1 is called in C./n");
                       }
          };
          int main()
          {
              B b;
              printf(" OK./n");
             
              C c;
            
              while(1);
              return 0;
          }
          /*
          result:
                call v1 in B.
                v1 is called in B.
                OK.
                call v1 in B.
                v1 is called in B.
                call v1 in C.
                v1 is called in A.
               
          */

     

     7. 多基派生中虚函数的二义性 :

     

    在本博的"继承"一篇中,提到了"同一基类多次拷贝引起的二义性",消除这种二义性的方法是把公共基类定义为虚基类。

    同样,多基派生中,虚函数也有这样的问题。具体来说,有两种场景:

    (1) 函数被定义为虚函数,但基类不是虚基类;

    (2) 函数被定义为虚函数,基类也被定义成虚基类。

     

    首先,看第一种情形:函数被定义为虚函数,但基类不是虚基类。

    下面程序中,

     

    A *a = &d 语句是错误的。

     

    因为不能使用指向公共基类A的指针来访问多条路径汇聚处的派生类D的对象。

     

    /* IDE环境: Dev-C++ 4.9.9.2 */

    /* 例4: virtual2.cpp */

     

    #include <stdio.h>

             

        class  A 

        {

               public :

                      virtual void test_func1() { printf("A::test_func1() /n"); }

                      virtual void test_func2() { printf("A::test_func2() /n"); }

                      virtual void test_func3() { printf("A::test_func3() /n"); }

         };

       

        class  B :  public  A

        {

               public :

                      virtual void test_func1() { printf("B::test_func1() /n"); }

                      virtual void test_func2() { printf("B::test_func2() /n"); }

        };

       

        class  C :  public  A

        {

               public :

                      virtual void test_func1() { printf("C::test_func1() /n"); }

                      virtual void test_func2() { printf("C::test_func2() /n"); }

                                      

        };

       

        class  D : public  B , public  C

        {

               public :

                      virtual void test_func1() { printf("D::test_func1() /n"); }

        };

       

        int main()

        {

            D d;

            //A *a = &d; // compile error: D:/devcpptest/virtual2.cpp `A' is an ambiguous base of `D'

                         // 因为:不能使用指向公共基类A的指针来访问多条路径汇聚处的派生类D的对象。

           

            B *b = &d; //OK. 可以使用指针指向类层次结构中无分支的某条路径上的某个类

            b->test_func1(); // 调用 D的test_func1

            b->test_func2(); // 调用 B的test_func2 

            b->test_func3(); // 调用 A的test_func3

           

            while(1);

            return 0;

        }

       

    /* result:

              D::test_func1()

              B::test_func2()

              A::test_func3()

    */

     

     

    从例4可以看出,在这种场景下,有:

     (1) 不能使用指向公共基类A的指针来访问多条路径汇聚处的派生类D的对象。

     (2) 只可以使用指针指向类层次结构中无分支的某条路径上的某个类。

     (3) 派生类中定义的函数可以覆盖基类中的同名函数,虚函数也不例外。

     

     

    再看第二种情形:虚基类中含有虚函数

    在例4类的定义的基础上,将基类A定义为B和C的虚基类,如下,

     

         class  B : virtual public  A

         class  C : virtual public  A,

        

    在这样的类层次结构中,就可以使用指向公共基类指针来访问派生类对象了,但是,这和编译器相关。

    有的编译器认为这种用法是正确的,有的认为是非法。

    如下:

        int main()

        {

            D d;

            A *a = &d;

            a->test_func1(); // 

            a->test_func2(); //  有的编译器认为这种用法是正确的,有的认为是非法。  

            a->test_func3(); // 

           

            while(1);

            return 0;

        }

    这时,会产生对函数test_func2()引用的二义性,因为test_func2()没有在D中重新定义,

    即在对象d中继承的test_func2()来自B还是C呢?这和编译器有关。有的编译器(如Borland C++)

    会以B与C作为D的基类的顺序有关,哪个在前,就用以哪个为准。GCC编译器会报错。

    在Borland C++ 中,上面运行的结果是:

    /* result:

              D::test_func1()

              B::test_func2() //因为是 class  D : public  B , public  C

                              //而不是 class  D : public  C , public  B

              A::test_func3()

    */

     

    /* 说明:

    result:

    1.  Borland C++ 中,正确运行, 结果如下:

              D::test_func1()

              B::test_func2() //因为是 class  D : public  B , public  C

                              //而不是 class  D : public  C , public  B

              A::test_func3()

     

    2.  VC6.0中,会有编译错误: 'D' : ambiguous inheritance of 'B::test_func2'

                                                       'D' : ambiguous inheritance of 'C::test_func2'

         Dev-C++ 4.9.9.2中,会有编译错误: no unique final overrider for `virtual void A::test_func2()' in `D'

    */

     

     

    8. 再给出一个虚函数的例子:

     

    /* 例5:virtual3.cpp   */

    /* IDE环境: Dev-C++ 4.9.9.2 */

    /* 虚函数举例 */

     

     

    #include <stdio.h>

    class point

    {

          private:

                  float x,y;

          public:

                 point(){printf("point::point/n");}

                 point(float i,float j)

                 {

                     printf("point::point(i,j)/n");

                     x =i;

                     y =j;

                 }

                 virtual float area()

                 {

                       return 0.0;

                 }

                 float girth()

                 {

                       printf("point::girth/n");

                       return 0.0;

                 }

          private:

                  void print()

                  {

                       printf("point::print/n");

                  }

    };

     

    const float PI = 3.14;

    class circle1: public point

    {

          private:

                  float r;

          public:

                 circle1(float r)

                 {

                     printf("circle1::circle1/n");

                     this->r = r;

                 }

                 float area()

                 {

                       return PI*r*r;

                 }

                 float gir()

                 {

                       printf("circle1::gir/n");

                       return PI*2*r;

                 }

         

                      

    };

     

    int main()

    {

         point *pp;

         circle1 c1(5.1);

         pp = &c1;

         printf("area of c1 = %f/n",pp->area());         //81.671700

         printf("area of c1 = %f/n",c1.point::area());   //0.000000

         printf("area of c1 = %f/n",c1.area());          //81.671700

        

         point *p = new circle1(2);  //1.其实是new了一个circle1的对象,而基类指针p又指向

                                     //这个对象,使得p可以访问circle1的area函数.

                                     //2.又由于这是一个point的指针,所以可以访问point的函数.

                                     //又,既然对象是circle1类型的,它继承了point的public函数,

                                     //所以,p肯定能够访问到自己类型的函数.

                                     //3.那么,circle1不继承point的private函数,p还能够访问

                                     //point的private函数么? 当然不能了,因为new的对象是

                                     //circel1的.p指向的实际上是circle1类型的对象,而这个

                                     //对象并没有继承point的private的函数.

                                    

         printf("area of p = %f/n",p->area()); //12.560000

        

        

         p->girth(); //ok,

         //p->print(); //error  

         //p->gir();  //error  

         //girth is function of point, gir is function of circle1,可以看出,p的确是

         //point的指针,而这个基类指针是可以访问派生类的area函数(这正是virtual function

         //的作用.但是,p不能访问派生类的gir函数,因为这个函数不是point的成员函数.

         while(1);

    }

     

    /* result:

        point::point

        circle1::circle1

        81.671400

        0.000000

        81.671400

        point::point

        circle1::circle1

        area of p = 12.560000

        point::girth

    */

     

    9. 后记:关于多态,虚函数,抽象类,纯虚函数这几个重要的概念与应用,请参考以下书籍:

        effectivec++

        c++编程思想第二版

        c++程序设计语言第三版

        C++ Primer 3rd Edition

     

       

     

     

     

     

    展开全文
  • iPhone开发秘籍(第2版)--源代码

    热门讨论 2012-12-11 13:51:22
    1.7.5 关于本书示例代码的说明 16 1.8 iPhone应用程序组件 17 1.8.1 应用程序文件夹层次结构 17 1.8.2 执行文件 17 1.8.3 Info.plist文件 17 1.8.4 图标和默认图像 19 1.8.5 NIB文件 20 1.8.6 应用程序束...
  • 1.什么多态? 1.1多态概念 1.每个对象都独立个体,拥有自己属性和方法,虽然拥有相同方法,但是运行结果可以不一样。...多态对代码具有可扩充性,增加新子类不影响已存在类多态性,继...

    1.什么是多态?

    1.1多态的概念

    1.每个对象都是独立的个体,拥有自己的属性和方法,虽然拥有相同的方法,但是运行结果可以是不一样的。
    2.多态是指两个或多个属于不同类的对象,对于同一个调用方法作出不同的响应的方法。

    1.2多态的优势

    1.2.1可替换性

    多态对已存在代码具有可替换性

    1.2.2可扩容性

    多态对代码具有可扩充性,增加新的子类不影响已存在类的多态性,继承性,以及其他特性的运行和操作。

    1.2.3灵活性

    它在应用中体现了灵活多样的操作,提高了使用效率。

    1.2.4简化性

    多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

    1.3多态的代码

    package com.lenovo.dt;
    
    public class Anmails {
        String color;
        String lengeh;
        public void eat() {
            System.out.println("蛇和狗是怎么吃东西的");
        }
        public void walk() {
            System.out.println("蛇和狗是怎么走路的");
        }
    
    }
    package com.lenovo.dt;
    
    public class Test1 {
        public static void main(String[] args) {
            Anmails a = new She();
            Anmails b = new Dog();
            a.eat();
            b.eat();
            a.walk();
            b.walk();
        }
    
    }
    package com.lenovo.dt;
    
    public class Dog extends Anmails{
    public void eat() {
    
        System.out.println("咬碎了吃");
        }
    public void walk() {
    
        System.out.println("在地上跑着走");
    }
    }
    package com.lenovo.dt;
    
    public class She extends Anmails{
    public void eat() {
        super.eat();
        System.out.println("直接吞下去");
    }
    public void walk() {
        super.walk();
        System.out.println("在地上游着走");
    }
    }

    运行出来结果为:
    蛇和狗是怎么吃东西的?
    直接吞下去
    咬碎了吃
    蛇和狗怎么走路的?
    在地上游着走
    在地上跑着走

    2.什么是接口?

    2.1接口的概念

    接口是一种规范,不需要关系通过这个接口可以完成什么功能。
    使用这个接口,就必须遵守这个接口的规范。
    (接口:接口是一种特殊的抽象类)

    2.2为什么使用接口

    1.只支持单继承
    2.可以实现多个接口
    3.接口可以精简程序结构,免除重复定义,提出设计规范。

    2.3如何定义一个接口

    public interface 接口名{
    抽象方法
    }
    接口的关键字是:interface

    五月十七日结束,期待明天。

    展开全文
  • 2020-10-24

    2020-10-24 12:38:05
    3.可扩充性:多态对代码具有可扩充性 4.接口性:多 态超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现 5.灵活性:它在应用中体现了灵活多样操作,提高了使用效率 6.简化性:多态简化对...
  • 继承定义与使用

    2020-02-29 22:08:47
    所谓良好的代码指的是结构合理、适合维护、重用很高,但是如果现在只是按照之前所学习概念进行程序定义,那么不避免要面对重复问题,下面定义两个类:人类、学生类,如果按照传统定义,则结构如下:...
  • java新手入门517

    2018-05-17 21:19:51
    什么是多态是指两个或多个属于不同类对象,对于同一个消息作出不同响应方式。 如何实现多态程序入口调用类实现Questions questions = new Answer1();...2.扩充性多态对代码具有可扩充性增加新子类...
  • 面向对象基本概念

    2019-07-24 19:01:01
    面向对象技术有三个特征,分别...多态同一类对象表现出的不同行为,编程应该尽可能利用多态实现数据的处理,这样做能够提高编程效率,提高程序的可维护性和可扩充性。 面向对象基本概念包括对象,抽象,封装...
  • java基础知识(7)

    2018-05-17 15:15:02
    多态是什么多态是指两个或多个属于不同类对象,对于同一个消息(方法调用)做出不同响应方式。如何实现多态程序入口调用实现Questions questions = new Answer1();...2、课扩充性多态对代码具有可扩充性。增加...
  • 多态和接口

    2018-05-24 20:12:25
    2.口诀:大手牵小手 父类在前 子类在后 编译时父类方法 运行时子类方法3多态优势: ①可替换性:多态对已存在代码具有替换性 ②可扩充性:多态代码具有可扩充性,增加新子类不影响已存在类多态...
  • java面向对象基础——多态 多态概念 多态指的是同一个方法调用,由于对象不同可能会...多态对代码具有可扩充性。增加新子类不影响已存在类多态性、继承性,以及其他特性运行和操作。 灵活性。它在应用中...
  • 所谓良好的代码指的是结构合理、适合于维护、重用很高,但是如果现在只是按照之前所学习到概念进行程序定义,那么不避免要面对重复问题,下面定义两个类:人类、学习类,如果按照传统定义,则结构...
  • java——类与对象

    2019-05-03 00:43:24
    面对对象:以一种主键化的形式进行代码的设计,最大的好处是可重用。 封装:保护内部的定义结构安全; 继承:在已有的程序结构上继续扩充新的功能; 多态在某一个概念范围内的满足。 开发步骤: ...
  • Java学习笔记(3)

    2021-03-04 10:47:01
    所谓良好的代码指的是结构型合理、适合于维护、重用高。 Java中实现继承类使用关键字extends,通常子类称为派生类,父类称为超类(superclass) 继承实现目的在于子类可以重用父类结构,并且可以扩充更多...
  • 可扩充性 接口性 灵活性 简化性 多态体现: 父类类型:子类对象继承父类类型,或者实现父接口类型。 父类类型 变量名 = new 子类对象; 变量名.方法名(); 代码如下: 父类 public abstract class Animal ...
  • 所谓良好的代码是指结构合理、适合用于维护、重用高。如果用之前学习概念定义,那么不避免面对重复问题。下面定义两个类:人类、学生类。那么按照传统定义,则结构如下: class person{ private ...
  • C++笔记(三)

    2020-12-15 23:44:35
    面向对象程序设计语言有封装、继承和多态三种机制,这三种机制能够有效提高程序可读性、可扩充性和可重用性。 多态(polymorphism)”指的是同一名字事物可以完成不同功能。多态可以分为编译时多态和运行时...
  • JAVA-理解多态

    2018-05-02 21:16:03
    前言   面向对象有三大特征:封装、继承、多态。 封装隐藏了类内部实现机制,可以在不影响使用者前提下改变类内部结构,继承为了重用父类代码,而多态呢?...3. 可扩充性 4. 接口性 5....
  • C++ 模板

    2017-10-13 15:09:00
    泛型程序设计与模板: 一种算法在实现时不指定具体要操作的数据的类型的程序设计方法...函数模板: 作用:面向对象的继承和多态机制有效的提高了程序的可重用性和可扩充性,但在可重用性的某些方面,程序员还希望得...
  • 面向过程:指的是针对某一个问题单独提出解决方案和代码开发。 面向对象:以组件化形式进行代码设计,优点是代码可重用。 面向对象语言特征: (1)封装:内部操作对外部不可见,保护内部结构安全。 (2)...
  • Java基础(十六)

    2018-10-31 18:34:47
    良好的代码指的是结构合理,适合于维护,可用高,重用高; 例如:要定义两个类:人类,学生类;两者都有姓名和年龄属性;发现有一些重复的代码出现在程序之中;进一步思考:学生一个人,人一个更加广泛...
  • 继承问题引出

    2020-12-09 15:00:28
    所谓良好的代码指的是结构合理、适合于维护、重用很高,但是如果现在只是按照之前所学习到概念进行程序定义,那么不避免要面对重复问题,下面定义两个类,如果按照传统定义,则结构如下: class ...
  • PHP面向对象-继承

    2019-06-01 16:25:06
    通过继承已有的类,可以逐步扩充类的功能,提高代码的可重用。 关键字:extends php中使用关键字extends可实现类的继承 语法格式 class 子类名 extends 父类名 { 定义子类成员变量; 定义子类成员函数; } 注意...
  • 继承派生基本概念

    2019-12-04 10:44:06
    软件开发提倡“重用”高,而C++引入继承机制正是提高代码可重用性的方式之一。 2、继承与派生基本概念 首先继承和派生讲的是一回事。 继承:在定义一个新类B时,如果该类与某个已有类A相似(指的是B拥有A...

空空如也

空空如也

1 2 3 4
收藏数 63
精华内容 25
关键字:

代码的可扩充性是指