我是C ++的新手,我遇到了麻烦。所以我正在尝试使用泛型子类创建可以调用彼此字段的类。
基本上,我正在尝试制作一个游戏,其中有一个泛型类型和三种类型相互优势/弱点。我只是真的有Java经验,而且这种事情的c ++翻译不是为了点击我
泛型类型分为三种类型:类型1,类型2,类型3。
通用类型需要具体
在泛型类型中有字段攻击,防御,命中点
类型1,2和3都继承这些字段。
我正在尝试在泛型类中创建一个虚函数:
virtual void attack(Generic* g);
问题是,当我尝试以type_1.attack(generic)
为例时,我想用g->命中点来获取通用的生命值,但它似乎在C ++中没有那样。
另外,我知道我一定做错了,因为类型1,2和3都包含泛型类型的标题,但如果我想在main.cpp中包含这3个标题,它会给我一个错误分别宣布通用3次。
我将如何做到这一点?
对不起,这是一个非常具体的问题,而且有点模糊。如果我需要澄清任何内容,请告诉我
编辑:这是我正在谈论的基本设置
//in generic.h
class Generic {
protected:
int hitpoints;
int strength;
int defense;
public:
virtual void attack(Generic* g);
};
//type1.h
#include 'generic.h'
class Type1 : public Generic {
void attack (Generic* g);
};
//in type1.cpp
void Type1::attack(Generic*g) {
g->hitpoints = strength - g->defense;
}
class Generic {
protected:
int hitpoints;
int strength;
int defense;
public:
virtual void attack(Generic* g);
};
//type1.h
#include 'generic.h'
class Type1 : public Generic {
void attack (Generic* g);
};
//in type1.cpp
void Type1::attack(Generic*g) {
g->hitpoints = strength - g->defense;
}
答案 0 :(得分:3)
对象可以访问从基类继承的自己的 protected
成员。但是对象无法访问其他对象的 protected
成员。这是private
与protected
之间的差异 - private
成员只能由声明它们的类访问,但protected
成员可以通过声明类及其hitpoints
成员访问后人。但是,两者仍然是外部代码的私有。
要执行您尝试的操作,public
必须为{{1}}。
答案 1 :(得分:1)
为了避免你的第二个问题(一个多次定义的类),有一些叫做 include guards 的东西(它们可以防止你多次包含同一个文件)。它的工作方式如下:
// File: type1.h
// At the very beginning
#ifndef type1_h
#define type1_h
// Here come the rest of your file and, at the end:
#endif
这样,文件的内容只包含一次,因为在定义type1_h
之后,所有内容都将被跳过。这可能是C ++中普遍接受的#define
的唯一用途。
至于你的第一个问题,protected
意味着派生类可以为自己或他们自己的类的对象读取该成员,但没有其他人。这包括派生类无法读取属于另一个类的对象的成员,包括基类本身。我担心你不得不重新考虑你的设计。
您可以做的最好的事情就是更改protected
成员的隐私,或者更好的是,提供public
个访问者并保留数据成员private
。 public
数据成员在类中很少是个好主意(结构是另一回事):
class Generic {
private:
int hitpoints;
int strength;
int defense;
public:
virtual void attack(Generic* g);
void SetHitpoints(int hp) {hitpoints = hp;}
int GetDefense() {return defense;}
};
答案 2 :(得分:1)
类型1,2和3都包含泛型类型的标题,但是如果我想在main.cpp中包含这3个标题,那么在单独声明3个通用时会给我一个错误。'
您需要确保该类仅声明一次。这通常使用.h文件中的警卫来完成:
//generic.h
#ifndef GENERIC_H
#define GENERIC_H
//all declarations go here
#endif /* GENERIC_H */
当您键入#include "generic.h"
时,C ++处理器基本上只会粘贴foo.h的内容。由于你将它包括三次(通过类Type1,Type2和Type3的包含,每个包括generic.h),该类被删除三次。
答案 3 :(得分:1)
你应该这样做:
// generic.h
#pragma once
class Generic {
protected:
int hitpoints_;
int strength_;
int defense_;
void do_damage(Generic* g, int damage) { g->hitpoints_ -= damage; }
public:
virtual void attack(Generic* g) = 0;
int hitpoints() const { return hitpoints_; }
int strength() const { return strength_; }
int defense() const { return defense_; }
};
// type1.cpp
void Type1::attack(Generic* g) {
do_damage(g, strength_ - g->defense());
}
答案 4 :(得分:1)
数据成员protected
的含义与您的预期略有不同。如果您的班级A
包含受保护的数据成员d
,并且该班级B
继承自A
(具有公共继承权),则B
为成员函数可以访问d
- 但仅限于B
类型的对象,而不是A
类型的任何对象。如果这看起来令人困惑,那么代码示例有望让它变得更加清晰:
class A {
protected:
int d;
};
class B : public A {
void fine(B& b) { b.d = 0; }
void wrong(A& a) { a.d = 0; }
};
int main() { }
如名称所示,函数fine
中的赋值是可以的,但如果您尝试编译代码,则会在wrong
中得到编译器错误。解决这个问题的最好方法可能是使数据成员保密,并编写对其进行操作的受保护成员函数,如abyss.7的答案。
对于双重包含问题,请使用include guards或#pragma once。