创建可以调用彼此的共享成员变量的子类

时间:2013-10-12 17:43:29

标签: c++ polymorphism

我是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; }

5 个答案:

答案 0 :(得分:3)

对象可以访问从基类继承的自己的 protected成员。但是对象无法访问其他对象的 protected成员。这是privateprotected之间的差异 - 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个访问者并保留数据成员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;}
};

答案 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