You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++纯虚函数重写异常:输出为0而非预期值

问题描述

运行以下C++代码后,输出结果为0,而非预期的角色名称和生命值。我尝试通过基类character定义接口,在子类entity中实现相关变量与方法,怀疑是不是虚函数未正确重写导致的问题?

#include <iostream>
using namespace std;

class character {
private:
public:
  character(string n, int h, int a){
  }
  virtual int getHealth() = 0;
  virtual int getAttack() = 0;
  virtual string getName() = 0;
  virtual void updateHealth() = 0;
  virtual void updateAttack(int a) = 0;
  virtual void attackCharacter(character &b) = 0;
  virtual void print() = 0;
};
class entity : public character {
private:
string name;
int health;
int attack;
public:
  entity(string n, int h, int a) : character(n, h, a) {
    n = name; h = health; a = attack;
  }
  void updateAttack(int a) override { attack = a; }
  void attackCharacter(character &b) override { b.updateHealth(); b.getHealth(); }
  int getHealth() override { return health; }
  string getName() override { return name; }
  virtual void print() override {cout<<name<<" "<<health<<endl;}
  int getAttack() override { return attack; }
 void updateHealth() override { health = health - attack; }
};

#include <iostream>
#include "character.h"
using namespace std;

int main() {
   character* player = new entity("Player", 50, 5);
   entity* enemy = new entity("Enemy", 50, 5);
   player->print();
   enemy->print();
  }
问题分析与修复

你的问题不是虚函数重写错误,而是几个基础逻辑和语法错误导致的:

  • 子类构造函数赋值顺序颠倒
    在entity的构造函数里,你写的是n = name; h = health; a = attack;——这是把未初始化的成员变量值赋给了参数,而非把参数值赋给成员变量。正确写法应该是:

    entity(string n, int h, int a) : character(n, h, a) {
      name = n; 
      health = h; 
      attack = a;
    }
    

    更简洁的初始化列表写法:

    entity(string n, int h, int a) : character(n, h, a), name(n), health(h), attack(a) {}
    

    原代码中成员变量未初始化,所以print()输出的是随机垃圾值(大概率为0)。

  • updateHealth方法逻辑错误
    当前updateHealth的实现是让自身生命值减去自身攻击力,完全不符合攻击逻辑。需要调整设计:

    1. 给基类的updateHealth添加参数,接收受到的伤害值:
      virtual void updateHealth(int damage) = 0;
      
    2. 子类重写该方法,用生命值减去伤害值:
      void updateHealth(int damage) override { health -= damage; }
      
    3. 修改attackCharacter,传入当前对象的攻击力作为伤害:
      void attackCharacter(character &b) override {
        b.updateHealth(getAttack());
      }
      
  • 冗余代码清理

    • 基类character是纯虚接口类,空构造函数无意义,可直接移除;
    • main前重复包含<iostream>,还引用了不存在的character.h,需删除这些冗余内容。
修复后的完整代码
#include <iostream>
#include <string>
using namespace std;

class character {
public:
  virtual int getHealth() = 0;
  virtual int getAttack() = 0;
  virtual string getName() = 0;
  virtual void updateHealth(int damage) = 0;
  virtual void updateAttack(int a) = 0;
  virtual void attackCharacter(character &b) = 0;
  virtual void print() = 0;
};

class entity : public character {
private:
  string name;
  int health;
  int attack;
public:
  entity(string n, int h, int a) : name(n), health(h), attack(a) {}
  
  void updateAttack(int a) override { attack = a; }
  
  void attackCharacter(character &b) override {
    b.updateHealth(getAttack());
  }
  
  int getHealth() override { return health; }
  
  string getName() override { return name; }
  
  void print() override {
    cout << name << " " << health << endl;
  }
  
  int getAttack() override { return attack; }
  
  void updateHealth(int damage) override { 
    health -= damage;
    if (health < 0) health = 0;
  }
};

int main() {
   character* player = new entity("Player", 50, 5);
   character* enemy = new entity("Enemy", 50, 5);
   
   player->print();
   enemy->print();
   
   // 测试攻击逻辑
   player->attackCharacter(*enemy);
   cout << "After player attacks enemy:" << endl;
   enemy->print();
   
   enemy->attackCharacter(*player);
   cout << "After enemy attacks player:" << endl;
   player->print();
   
   delete player;
   delete enemy;
  }

内容的提问来源于stack exchange,提问作者Ferndle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:25:22