c++ 重写 多态

1 重写(继承后(拼接基类后))

1.1 非虚函数 同名成员函数 (各自有一个xFunction() 内存 )

#include <iostream>
#include <String>
class BaseClass {
public:
  void xFunction() {
    std::cout << "BaseClass::xFunction()\n";  
  }
};

class Subclass1 : public BaseClass { 
public:
  void xFunction() {
    std::cout << "Subclass1::xFunction()\n";

  }  
};


int main() {
  Subclass1 subclass1;
  subclass1.xFunction();
  return 0;  
}

输出:

Subclass1::xFunction()

基类对象内存布局:
+-------------+ 
| 其他成员变量 |
+-------------+
| xFunction() | -> 基类xFunction()函数的代码      
+-------------+

子类对象内存布局:  
+-------------+
| 基类部分   |   // 继承而来的基类的数据和方法
+-------------+ 
| 子类独有成员变量 |    
+-------------+
| xFunction() | -> 子类xFunction()函数的代码  
+-------------+

运行原则是:

  1. 子类对象可以直接访问继承而来的基类的数据和方法
  2. 当子类与基类存在同名函数时,根据就近原则,通过子类对象访问同名函数时,会调用子类自己的同名函数,即这里的Subclass1::xFunction()
  3. 如果要访问基类中被隐藏的同名函数,需要使用作用域解析运算符,如subclass1.BaseClass::xFunction()

所以在这个例子中,通过subclass1.xFunction()调用时,执行的就是子类中重写的xFunction()函数,输出"Subclass1::xFunction()"。

1.1.2 多次实例化subclass1对象 (就是多次创建应用这个类 开内存)

每个实例化对像的成员变量 内存是单独的

成员函数是多个此类实例对象 公用子类 基类的成员函数 用类:: 指明

成员函数代码区(共享):

┌──────────────────────────────┐
│ 成员函数代码                  │  
│ (包括 BaseClass::xFunction)  │
│ (包括 Subclass1::xFunction)  │
└──────────────────────────────┘

subclass1对象实例1:
┌──────────────────────────────┐
│ 成员变量                      │ 
└──────────────────────────────┘

subclass1对象实例2: 
┌──────────────────────────────┐
│ 成员变量                      │
└──────────────────────────────┘

1.2 虚函数virtual (只有一个xFunction()内存 在基类中, 重写就覆盖)

#include <iostream>
#include <String>
class BaseClass {
public:
  virtual void xFunction() {
    std::cout << "BaseClass::xFunction()\n";  
  }
};

class Subclass1 : public BaseClass { 
public:
  void xFunction() {
    std::cout << "Subclass1::xFunction()\n";

  }  
};


int main() {
  Subclass1 subclass1;
  subclass1.xFunction();
  return 0;  
}
+------------------------+
|        subclass1       |
+------------------------+
|  vptr (指向虚函数表)   |
+------------------------+
|                        |
|                        |
|                        |
|                        |
|                        |
|                        |
|                        |
|                        |
+------------------------+

+------------------------+
|       BaseClass        |
+------------------------+
|  vtable (虚函数表)     |
+------------------------+
|  xFunction()           |
+------------------------+

就是subclass1存的是基类的xFunction()地址的地址?

是的,您的理解是正确的。
subclass1中存的是指向基类中xFunction()这个成员函数的指针的地址。
所以它是一个二级指针。

2 多态(子类用基类模板创建/增加不同功能)

#include <iostream>

class Operation {
public:
    virtual int calculate(int a, int b) = 0; // 纯虚函数,需要在子类中实现
};

class Addition : public Operation {
public:
    int calculate(int a, int b) override {
        return a + b;
    }
};

class Subtraction : public Operation {
public:
    int calculate(int a, int b) override {
        return a - b;
    }
};

int main() {
    Operation* op1 = new Addition(); // 创建加法类对象,并将其指针赋值给基类指针
    Operation* op2 = new Subtraction(); // 创建减法类对象,并将其指针赋值给基类指针

    int result1 = op1->calculate(5, 3); // 调用加法类的calculate函数
    int result2 = op2->calculate(5, 3); // 调用减法类的calculate函数

    std::cout << "Result1: " << result1 << std::endl; // 输出加法计算结果
    std::cout << "Result2: " << result2 << std::endl; // 输出减法计算结果

    delete op1;
    delete op2;

    return 0;
}

Operation* op1 = new Addition(); 创建对象并开内存 并给基类一个初始地址,;

然后根据这个地址 基类分配各个成员的空间;

初始化完 基类Operation被改造有成员变量calculate();

子类 只有指向基类的地址 用于找到虚函数 成员变量;

+------------------------+
|       Operation        |
+------------------------+
|  vtable (虚函数表) |
+------------------------+
|  calculate()            |
+------------------------+

+------------------------+
|        Subtraction    |
+------------------------+
|  vptr (指向虚函数表)   |
+------------------------+

3

3.1

Operation* op1 = new Addition();

3.2 & 取地址符号

Addition add; // 创建命名的 Addition 对象
Operation* op1 = &add; // 将对象的地址赋值给基类指针

是的,Operation* op1 = new Addition();这一行代码是在堆内存上动态分配了一个Addition对象。

具体来说:

  1. new Addition() 在堆内存上创建了一个Addition对象,并返回该对象的地址

  2. Operation* op1 定义了一个Operation类型的指针op1

  3. = 将new Addition()返回的Addition对象的地址赋值给了指针op1

所以,op1指向了堆内存中动态分配的那个Addition对象。

而Addition add这行代码是在栈内存上创建了一个Addition类型的对象add。

两者的区别在于:

  1. new创建的是在堆内存上的对象
  2. 直接创建如Addition add的是在栈内存上的对象

堆内存对象的生命周期由程序员控制,栈内存对象的生命周期随着函数的结束而结束。

将Addition对象的地址赋值给Operation*类型的指针op1,实现了基类指针指向子类对象的效果,可以实现多态。这是面向对象编程中非常重要的概念。

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值