继承和重写

继承(extends)

  • 基于已有类(父类)创建新类(子类)的一种方式
  • object类默认为所有类的父类
  • 子类继承父类里的方法
  • JAVA中一个类只能继承一个父类
  • 若一个类由final修饰,则它没有子类 例:String、System、
    基本数据包装类型(int-Interger,Byte,Short,Long,Float,Double
    ,Boolean,CHaracter)
  • 父类中并非所有的方法和成员变量子类都能继承(修饰符private)
  • 子类可以调用父类的成员变量(若两者中有同名的成员变量,则子类调用的是自己的成员变量)
public class father {
    int num;
    String address;
    public void first() {
        System.out.println("function in father");
    }
}

public class son extends father {
    public void second() {
        System.out.println("function in son");
    }
}

public class test {
    public static void main(String[]args ) {
        son s = new son();
        s.first();//子类调用父类对象
        s.second();
    }
}

方法重写

  • 定义:在Java和其他一些高级面向对象的编程语言中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
  • 重写后的方法可以用override注解修饰
  • 若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数列表(虚参的名字可以不同,其余必须相同),则新方法将覆盖原有的方法。
  • 返回类型:
    a、如果父类中的方法返回类型为void或基本数据类型,则需保持一致
    b、如果父类中的方法返回类型为引用类型,则保持一致或父类方法返回值的子类
  • super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
    this关键字:指向自己的引用。
  • 重写后方法的访问权限(public protected private)只能大于等于父类的
  • 父类中final、static修饰的方法,子类可继承不可重写
    父类中private修饰的方法,子类不可继承不可重写
  • 子类重写后的方法不能用static修饰
public class father {
    int num;
    String address;
    public void first() {
        System.out.println("function in father");
    }
}

public class son extends father {
    public void second() {
        System.out.println("function in son");
    }
    public  void first() {
        System.out.println("function in father but override");
    }
    void test() {
        this.first();//自己类
        super.first();//父类
    }
}

public class test {
    public static void main(String[]args ) {
        son s = new son();
        s.first();
        s.test();
    }
}
<think>我们正在讨论C++中的类继承方法重写。根据之前的引用内容,我们可以总结以下关键点: 引用[1]提到: - 如果派生类的函数与基类的函数同名同参数,但基类函数没有virtual关键字,则基类的函数被隐藏(不是覆盖)。 - 重载发生在同一作用域,函数名相同但参数不同;重写(覆盖)发生在继承关系中,要求基类函数有virtual关键字,且函数签名相同。 - 静态方法可以被继承但不能被重写(覆盖),但可以在子类中被隐藏(通过定义同名的静态方法)。 引用[2]虽然讲的是Java,但其中关于重写的规定(方法名形参列表相同,权限修饰符不小于父类)在C++中也有类似概念(C++中通过virtualoverride关键字)。 引用[3]给出了一个重定义(隐藏)的例子: - 在派生类中定义了一个与基类同名但参数不同的函数,这会隐藏基类的同名函数。如果想调用基类的被隐藏函数,需要使用作用域解析运算符(如`A::fun()`)。 引用[4]提到了实现继承的作用,即子类可以重用基类的代码。 现在,用户的问题是:了解C++中类继承方法重写的实现方式。 因此,我们需要详细解释C++中类继承方法重写的机制,包括: 1. 继承的基本语法 2. 方法重写(覆盖)的条件实现 3. 方法隐藏(重定义)的概念 4. 虚函数表动态绑定的原理(效率方面) 5. 使用override关键字(C++11)的好处 同时,根据系统指令,我们需要: - 使用LaTeX格式表示数学表达式公式 - 代码块使用正确语法高亮 - 在回答末尾生成相关问题 下面开始组织回答。 </think> ### C++类继承与方法重写的实现详解 #### 一、继承基础实现 C++通过`class Derived : access-specifier BaseClass`语法实现继承: ```cpp class Shape { // 基类 protected: double x, y; public: void setPosition(double a, double b) { x = a; y = b; // 可被子类继承的方法 } }; class Circle : public Shape { // 公有继承 private: double radius; public: double area() const { return 3.14 * radius * radius; } }; ``` - **内存布局**:派生类对象包含基类子对象 `sizeof(Circle) = sizeof(Shape) + sizeof(double)` - **访问控制**: - `public继承`:基类public→派生类public,protected→protected - `protected继承`:基类public/protected→派生类protected - `private继承`:基类所有成员→派生类private #### 二、方法重写(覆盖)实现 需同时满足三个条件: 1. 基类方法声明为`virtual` 2. 派生类方法**同名、同参数、同返回类型** 3. 访问权限不更严格(通常保持`public`) ```cpp class Animal { public: virtual void speak() const { // 虚函数声明 std::cout << "Animal sound\n"; } }; class Cat : public Animal { public: void speak() const override { // C++11显式重写标识 std::cout << "Meow\n"; // 覆盖基类实现 } }; ``` **动态绑定原理**: ```cpp Animal* pet = new Cat(); pet->speak(); // 输出"Meow"(调用Cat::speak) ``` - 通过**虚函数表(vtable)** 实现运行时多态 - 每个含虚函数的类拥有vtable,存储函数指针 - 对象隐含`vptr`指针指向对应vtable #### 三、方法隐藏(重定义) 当基类方法**非虚**时,派生类同名方法会隐藏基类版本: ```cpp class Base { public: void print(int x) { std::cout << "Base: " << x; } }; class Derived : public Base { public: void print(const char* s) { // 隐藏Base::print(int) std::cout << "Derived: " << s; } }; Derived d; d.print(10); // ❌ 编译错误:隐藏基类int版本 d.Base::print(10); // ✅ 显式调用基类方法 ``` 特征: 1. 作用域不同(基类 vs 派生类) 2. 不需要virtual关键字 3. 可通过作用域运算符`::`访问被隐藏方法 #### 四、关键对比表 | 特性 | 重写(Override) | 隐藏(Hiding) | 重载(Overload) | |-------------|-----------------------|--------------------|--------------------| | **作用域** | 不同类(继承关系) | 不同类(继承关系) | 同一类 | | **virtual** | 必须 | 不需要 | 不需要 | | **签名** | 完全相同 | 函数名相同即可 | 参数类型/数量不同 | | **绑定** | 动态(运行时) | 静态(编译时) | 静态(编译时) | | **访问** | `override`显式声明(C++11)| 自动隐藏 | 自动区分 | #### 五、继承中的特殊场景 1. **纯虚函数与接口继承** ```cpp class AbstractShape { // 接口类 public: virtual double area() const = 0; // 纯虚函数 }; class Square : public AbstractShape { public: double area() const override { /* 必须实现 */ } }; ``` 2. **防止继承**(C++11) ```cpp class FinalClass final { /* 不能被继承 */ }; ``` 3. **构造函数与析构函数** - 基类析构函数应声明为`virtual`(避免资源泄漏) - 构造函数不能虚 #### 六、性能影响 - **虚函数调用成本**:多一次指针解引用(访问vtable),约多消耗 5-10 CPU周期 - **空间开销**:每个对象增加`vptr`指针(通常 4-8 字节) - **优化建议**: - 对性能关键路径,优先使用编译期绑定(模板/CRTP) - 小对象频繁调用时慎用虚函数 > 通过继承多态实现"开放-封闭原则":对扩展开放,对修改关闭[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值