返回

通俗易懂:继承易错点分析

后端

了解继承易错点,少走弯路,更显代码功底。

继承易错点:基类private成员的继承

  1. 基类private成员的访问权限:

    • 私有成员只能在定义它的类及其友元类中访问。
    • 错误示例:
      class Base {
          private int privateMember = 10;
      }
      
      class Derived extends Base {
          public void accessPrivateMember() {
              System.out.println(privateMember); // 编译器错误:privateMember不可访问
          }
      }
      
  2. 基类private方法的访问权限:

    • 私有方法只能在定义它的类中调用。
    • 错误示例:
      class Base {
          private void privateMethod() {
              System.out.println("Private method");
          }
      }
      
      class Derived extends Base {
          public void accessPrivateMethod() {
              privateMethod(); // 编译器错误:privateMethod不可访问
          }
      }
      

解决方法:

  • 如果需要在派生类中访问基类的私有成员或方法,可以使用友元类。友元类可以访问另一个类的私有成员和方法。
  • 谨慎使用私有成员和方法。在需要严格控制访问权限时才使用私有成员和方法。
  • 在继承中,基类的protected成员在派生类中是可见的,但不能直接访问。需要通过基类指针或引用来访问。

继承易错点:构造函数和析构函数的继承

  1. 构造函数的继承:

    • 构造函数不能被继承。
    • 派生类不能显式调用基类的构造函数。
    • 错误示例:
      class Base {
          public Base() {
              System.out.println("Base constructor");
          }
      }
      
      class Derived extends Base {
          public Derived() {
              Base(); // 编译器错误:不能调用基类的构造函数
          }
      }
      
  2. 析构函数的继承:

    • 析构函数可以被继承。
    • 派生类的析构函数会自动调用基类的析构函数。
    • 错误示例:
      class Base {
          ~Base() {
              System.out.println("Base destructor");
          }
      }
      
      class Derived extends Base {
          ~Derived() {
              // 忘记调用基类的析构函数
          }
      }
      

解决方法:

  • 派生类的构造函数应该显式调用基类的构造函数。
  • 派生类的析构函数应该显式调用基类的析构函数。

继承易错点:基类的成员覆盖

  1. 成员覆盖(Overriding):

    • 派生类可以覆盖基类的非私有成员。
    • 覆盖的成员必须具有相同的名称和参数类型。
    • 覆盖的成员可以具有不同的访问权限,但不能比基类的成员更严格。
    • 错误示例:
      class Base {
          public void publicMethod() {
              System.out.println("Base public method");
          }
      }
      
      class Derived extends Base {
          private void publicMethod() { // 编译器错误:覆盖的成员不能比基类的成员更严格
              System.out.println("Derived private method");
          }
      }
      
  2. 虚函数(Virtual Function):

    • 虚函数是允许派生类覆盖的函数。
    • 虚函数通常使用virtual来声明。
    • 虚函数可以在派生类中被重新定义,以实现不同的功能。
    • 错误示例:
      class Base {
      public virtual void virtualMethod() {
          System.out.println("Base virtual method");
      }
      };
      
      class Derived : public Base {
      public virtual void virtualMethod() {
          System.out.println("Derived virtual method");
      }
      };
      
      class GrandDerived : public Derived {
      public void virtualMethod() { // 编译器错误:GrandDerived类没有覆盖virtualMethod
          System.out.println("GrandDerived virtual method");
      }
      };
      

解决方法:

  • 确保派生类的覆盖成员具有相同的名称和参数类型。
  • 确保派生类的覆盖成员可以具有不同的访问权限,但不能比基类的成员更严格。
  • 使用virtual关键字来声明虚函数,以便允许派生类覆盖。
  • 确保派生类覆盖了基类的虚函数,否则将导致编译器错误。

结论

继承是面向对象编程中的重要概念,但同时也是一个容易出错的地方。了解继承中的易错点,可以避免在编码中踩坑,写出更健壮、更可靠的代码。