无法在构造函数中访问类的继承成员
Posted
技术标签:
【中文标题】无法在构造函数中访问类的继承成员【英文标题】:Can't access inherited members of class in constructor 【发布时间】:2016-06-27 19:33:40 【问题描述】:我是 C++ 新手。我有简单的 Unit 类和 hero 类,它们是 Unit 类的继承。 Hero 类有 2 个附加参数,但构造函数无法访问父类的参数。 这是unit.hpp:
#ifndef UNIT_HPP
#define UNIT_HPP
#include <string>
using namespace std;
class Unit
public:
unsigned short max_health = 100;
string name = "Dummy";
short health = 100;
short damage = 10;
bool isDead = 0;
Unit();
Unit(string, unsigned short, unsigned short);
;
#endif //UNIT_HPP
这里是unit.cpp:
#include <string>
#include <iostream>
#include "unit.hpp"
using namespace std;
Unit::Unit()
cout << "Dummy was created!" << endl;
;
Unit::Unit(string N, unsigned short HP, unsigned short AT):
max_health(HP),
name(N),
health(HP),
damage(AT)
cout << N << " was created!" << endl;
;
这里是 hero.hpp:
#ifndef HERO_HPP
#define HERO_HPP
#include <string>
#include "unit.hpp"
class Hero : public Unit
public:
unsigned short max_mana = 100;
string name = "The Brave Warrior";
short mana = 100;
Hero (string, unsigned short, unsigned short, unsigned short);
;
#endif //HERO_HPP
最后,这里是 hero.cpp:
#include <string>
#include "hero.hpp"
using namespace std;
Hero::Hero(string N, unsigned short HP, unsigned short MP, unsigned short AT):
max_health(HP),
max_mana(MP),
name(N),
health(HP),
mana(MP),
damage(AT)
cout << "The Legendary Hero, " << N << ", was born!" << endl;
这是控制台输出:
src/hero.cpp: In constructor ‘Hero::Hero(std::__cxx11::string, short unsigned int, short unsigned int, short unsigned int)’:
src/hero.cpp:10:5: error: class ‘Hero’ does not have any field named ‘max_health’
max_health(HP),
^
src/hero.cpp:13:5: error: class ‘Hero’ does not have any field named ‘health’
health(HP),
^
src/hero.cpp:15:5: error: class ‘Hero’ does not have any field named ‘damage’
damage(AT)
^
问题出在哪里?抱歉英语不好。我希望我问的问题是对的,对我来说有这么多新术语。先感谢您。
【问题讨论】:
您想从初始化列表中调用基类构造函数,或者您可以在派生构造函数的主体中访问这些成员。 如果你想使用空间节省数据类型,你应该使用uint#_t
类型,例如uint8_t
和uint16_t
。这些类型有保证的大小。 short
类型保证至少具有给定的范围;它可以支持更大。例如,一个 32 位整数可以用作 short
并且仍然在语言规则范围内。
【参考方案1】:
你的基类应该负责初始化它的变量,通常是通过一个构造函数方法。
这个:
unsigned short max_health = 100;
string name = "Dummy";
short health = 100;
short damage = 10;
bool isDead = 0;
看起来不洁净。这些成员应该在构造函数中初始化:
Unit::Unit()
: max_health(100),
name("Dummy"),
health(100),
damage(10),
isDead(false)
;
另外,对于bool
变量,您应该使用true
或false
,而不是数字。
编辑 1:重复的成员名称 您的子类应避免使用与基类相同的变量名。
英雄中的台词:
string name;
隐藏或隐藏基类成员:
string name;
如果你更愿意遵守这个约定,你应该使用 范围解析操作符 ::
告诉编译器你指的是哪个成员:
Hero::name = "Hercules"; // Assign member in Hero class
Unit::name = "Person"; // Assign to member in Unit class.
【讨论】:
顺便说一句,没有必要使用short
数据类型,除非您在内存受限的系统上。 int
类型通常是处理器寄存器或字大小的类型。所以在 32 位平台上,处理器的寄存器大小通常是 32 位。使用较小的变量(字符除外)不会显着节省空间或提高效率。
感谢您的建议!我使用 short 只是因为我的系统是 x64 并且我想限制最大健康,所以它不会超过 9000 :) 另外,我删除了重复项。
如果这个答案有帮助,请点击复选标记。
这很有帮助,但对我的问题没有帮助。 Evan 的解决方案修复了它。【参考方案2】:
C++ 不允许您从子类的初始化列表中初始化基类的成员。
做
Hero::Hero(string N, unsigned short HP, unsigned short MP, unsigned short AT):
Unit(N, HP, AT), // initializes the base class' members
max_mana(MP),
name(N),
mana(MP),
// but you could override the base class' members here
isDead = true;
cout << "The Legendary Hero, " << N << ", was zombified!" << endl;
此外,您在 Unit 和 Hero 中都有一个名为“name”的成员,您可能希望删除或重命名其中之一。
【讨论】:
【参考方案3】:在 Unit 的构造函数中初始化 Unit 的成员(如果你只想从 Hero 中调用它,可能是一个受保护的成员),以及在 Hero 中的 Hero 的成员。这就是初始化列表的工作方式。或者,您可以在 Hero 的 ctor 的大括号之间初始化它们,但不建议这样做。
【讨论】:
【参考方案4】:您在 Hero.cpp 构造函数中尝试做的是初始化基类的成员。这听起来很像基类本身的工作!事实上,当到达分号时,可以说,基类构造函数 Unit() 已经被调用(因此,它包含的内容已经被初始化)。所以,如果你从 Unit 中删除 Unit(),你会得到一个编译错误,因为另一个构造函数有参数要接受。而那些你必须像这样明确指定的:
Hero::Hero(string N, unsigned short HP, unsigned short MP, unsigned short AT):
Unit(HP, N, HP, AT),
max_mana(MP),
mana(MP),
请注意,这里根本没有调用 Unit() - 只有另一个构造函数是 - 显式调用的。
【讨论】:
以上是关于无法在构造函数中访问类的继承成员的主要内容,如果未能解决你的问题,请参考以下文章