1

我是 C++ 新手,我遇到了麻烦。所以我正在尝试制作可以使用通用子类调用彼此字段的类。

基本上,我正在尝试制作一个游戏,其中有一个通用类型和三种类型,它们彼此具有优势/劣势。我真的只有 Java 方面的经验,而这种事情的 c++ 翻译对我来说并不合适

泛型类型分为三种类型:类型 1、类型 2、类型 3。

泛型类型需要具体

在通用类型中有字段攻击,防御,生命值

类型 1、2 和 3 都继承了这些字段。

我正在尝试在泛型类中创建一个虚函数:

virtual void attack(Generic* g);

问题是,例如,当我尝试制作时type_1.attack(generic),我想做 g->hitpoints 来获取泛型的生命值,但它似乎不像在 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;
}

4

5 回答 5

3

An object can access its own protected members that are inherited from a base class. But an object cannot access another object's protected members. That is the difference between private vs protected - private members can only be accessed by the class that declares them, but protected members can be accessed by the declaring class and its descendants. Both are still private to outside code, though.

To do what you are attempting, hitpoints needs to be public.

于 2013-10-12T18:09:47.717 回答
1

为了避免您的第二个问题(多次定义的类),有一种称为包含防护的东西(它们可以防止您多次包含同一个文件)。它的工作方式如下:

// 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将被定义,所以所有内容都将被跳过。这可能是唯一的用途#defineC++ 中普遍接受的唯一用法。

至于你的第一个问题,protected意味着派生类可以为自己或自己类的对象读取该成员,但不能读取其他人。这包括派生类无法读取属于另一个类的对象的该成员,包括基类本身。恐怕您将不得不重新考虑您的设计。

您能做的最好的事情就是改变protected成员的隐私,或者更好的是,提供public访问者并保留数据成员privatepublic数据成员在类中很少是一个好主意(结构是另一回事):

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;}
};
于 2013-10-12T18:05:53.870 回答
1

type 1, 2 and 3 all include the generic type's header, but if I want to include those 3 headers in main.cpp, it'll give me an error for declaring generic 3 separate times.'

You need to make sure that the class is declared only once. This is usually done with guards in the .h file:

//generic.h
#ifndef GENERIC_H
#define GENERIC_H

//all declarations go here

#endif /* GENERIC_H */

When you type #include "generic.h", the C++ processor will basically just paste the contents of foo.h. Since you included it thrice (via the includes for classes Type1, Type2 and Type3, that each include generic.h), the class is delcared three times.

于 2013-10-12T18:07:19.607 回答
1

protectedfor data members的含义与您可能期望的略有不同。当您有一个A具有受保护数据成员d的类和一个B继承自A(具有公共继承)的类时, thenB的成员函数可以访问d——但只能访问 type 的对象B,不能访问任何 type 的对象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

于 2013-10-12T19:27:46.010 回答
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());
 }
于 2013-10-12T18:15:19.307 回答