跳至主要內容

Different

LincZero大约 5 分钟

Different

目录

继承

继承 - 类继承

继承

  • java (在Java中,所有的继承都是公有继承,而没有C++中的私有继承和保护继承)

    public class Manager extends Employee
    {
        // ...
    }
    
  • C++

    class A : public APerent {}
    

多继承(不支持)

  • C++支持多继承
  • Java不支持多继承

继承 - 方法继承

重载、覆盖、隐藏(override、Override、hide)

C++中的重载、覆盖、隐藏(override、Override、hide)

  • 相同范围:重载

  • 不同范围:覆盖或隐藏(即:继承 x 多态)

    函数名参数基类有virtual关键字结果
    相同不同有或无隐藏
    相同相同隐藏
    相同相同覆盖

Java中的重载、覆盖、隐藏(override、Override、hide)

  • 不同范围

    函数名参数Java默认使用动态绑定,否则final结果
    相同不相——??
    相同相同——覆盖

覆盖方法、选择方法版本

  • 继承(inheritance):子类自动地继承了父类中的方法

  • 覆盖(Override):提供一个新的方法来覆盖(Override)超类中的原方法

    • 如果希望调用超类而不是子类的方法

      • Java:使用特定的关键字super解决这个问题

        super.getSalary()
        
      • C++:使用::

        父类名::getSalary()
        
    • 注意:有些人认为super与this引用是类似的概念,实际上,这样比较并不太恰当。这是因为super不是一个对象的引用,不能将super赋给另一个对象变量,它只是一个指示编译器调用超类方法的特殊关键字

子类构造器

C++

A::A():PerentA(){}
// 一般使用成员初始化列表语法(效率高)来调用基类构造函数
// 缺省时:
//     如果省略基类的构造函数,则程序自动使用默认的基类构造函数

Java

public Manager(String name, double salarym, int year, int month, int day)
{
    super(name, salary, year, month, day);
    // 使用super调用构造器的语句必须是子类构造器的【第一条】语句
    // 这里的关键字super具有不同的含义
    // 是“调用超类Employee中含有n、s、year、month和day参数的构造器”的简写形式
    bonus = 0;
}
// 缺省时:
//     如果子类的构造器没有显式地调用超类的构造器,则将自动地调用超类默认(没有参数)的构造器
//     如果超类没有不带参数的构造器,并且在子类的构造器中又没有显式地调用超类的其他构造器,则Java编译器将报告错误。

动态绑定

  • 一个对象变量(例如,变量e)可以指示多种实际类型的现象被称为多态(polymorphism)

  • 在运行时能够自动地选择调用哪个方法的现象称为动态绑定(dynamic binding)

  • C:默认是静态绑定

  • Java:不需要将方法声明为虚拟方法。动态绑定是默认的处理方式。如果不希望让一个方法具有虚拟特征,可以将它标记为final

继承 - 其他

阻止继承

Java

  • 作用1:不允许类被继承 例如,假设希望阻止人们定义Executive类的子类,就可以在定义这个类的时候,使用final修饰符声明

    public final class Executive extends Manager
    {
        ...
    }
    
  • 作用2:不允许类方法被复写 类中的特定方法也可以被声明为final。如果这样做,子类就不能覆盖这个方法(final类中的所有方法自动地成为final方法)

    public class Emplyee
    {
        ...
        public final String getName()
        {
            return name;
        }
        ...
    }
    

C++11,final关键字

  • 作用1:不允许类被继承

    struct Basel final{};		// 不让别人继承自己
    struct Derived1:Base1 {};	// 此时会报错
    
  • 作用2:不允许类方法被复写

    struct Base2{
        virtual void f() final;	// 不允许被复写
    };
    struct Derived2:Base2{
        void f();
    }
    

用途:将方法或类声明为final主要目的是:确保它们不会在子类中改变语义。例如在Java中:

  • Calendar类中的getTime和setTime方法都声明为final 这表明Calendar类的设计者负责实现Date类与日历状态之间的转换,而不允许子类处理这些问题
  • String类也是final类 这意味着不允许任何人定义String的子类。 换言之,如果有一个String的引用,它引用的一定是一个String对象,而不可能是其他类的对象。

方法/域的访问权限(保护访问)

  • Java

    • // priveate:仅对本类可见
      // public:对所有类可见
      // protected:对本包和所有子类可见
      // 默认:对本包可见
      
  • C++

    • 基本同上
  • 总结

    • Java中的受保护部分对所有子类及同一个包中的所有其他类都可见。这与C++中的保护机制稍有不同
    • Java中的protected概念要比C++中的安全性差

【功能扩展】继承

【功能扩展】继承 x 转换,强制类型转换

与C++不同

  • 类型转换 Java使用的类型转换语法来源于C语言,但处理过程却有些像C++的dynamic_cast操作。以下两种写法等价

    • Java

      Manager boss = (Manager) staff[1];					// Java
      
    • C++

      Manager* boss = dynamic_cast<Manager*>(staff[1]);	// C++
      
  • 判断是否能转换

    • Java:当类型转换失败时,抛出一个异常(有点像C++中的引用(reference)转换)

      if (staff[1] instanceof Manager)					// Java,需要将instanceof运算符和类型转换组合起来使用
      {
          boss = (Manager) staff[1];
          ...
      }
      
    • C++:当类型转换失败时,生成一个null对象

      Manager* boss = dynamic_cast<Manager*>(staff[1]);	// C++,直接转换
      if (boss != NULL) ...