头部防护问题 - 吞下活力

时间:2013-10-28 19:45:20

标签: c++ header include-guards

我完全已经结束了:我无法弄清楚我的依赖性是如何发生的。我已经阅读了无数的帖子和博客,并重复了我的代码很多次,我甚至不记得几乎工作和什么没有。我不仅不断获得重新定义错误,而且还定义了未定义错误的类。我重写了标题保护并删除了一些错误,只是为了找到其他人。我以某种方式将一切都归结为一个错误,但是当试图修复它时甚至已经破了。

请你帮我解决问题?

card.cpp

#include <iostream>
#include <cctype>
#include "card.h"

using namespace std;

// ====DECL======
Card::Card()
{
  abilities = 0;
  flavorText = 0;
  keywords = 0;
  artifact = 0;
  classType = new char[strlen("Card") + 1];
  classType = "Card";
}



Card::~Card (){
  delete name;
  delete abilities;
  delete flavorText;
  artifact = NULL;
}

   // ------------
Card::Card(const Card & to_copy)
{

  name = new char[strlen(to_copy.name) +1];         // creating dynamic array
  strcpy(to_copy.name, name);

  type = to_copy.type;
  color = to_copy.color;
  manaCost = to_copy.manaCost;

  abilities = new char[strlen(to_copy.abilities) +1];
  strcpy(abilities, to_copy.abilities);

  flavorText = new char[strlen(to_copy.flavorText) +1];
  strcpy(flavorText, to_copy.flavorText);

  keywords = new char[strlen(to_copy.keywords) +1];
  strcpy(keywords, to_copy.keywords);

  inPlay = to_copy.inPlay;
  tapped = to_copy.tapped;
  enchanted = to_copy.enchanted;
  cursed = to_copy.cursed;

  if (to_copy.type != ARTIFACT)
    artifact = to_copy.artifact;
 }

// ====DECL=====
int Card::equipArtifact(Artifact* to_equip){
  artifact = to_equip;
}

Artifact * Card::unequipArtifact(Card * unequip_from){
   Artifact * to_remove = artifact;
   artifact = NULL;
   return to_remove;
  // put card in hand or in graveyard
}

int Card::enchant( Card * to_enchant){
  to_enchant->enchanted = true;
  cout << "enchanted" << endl;
}

int Card::disenchant( Card * to_disenchant){
  to_disenchant->enchanted = false;
  cout << "Enchantment Removed" << endl;
}

// ========DECL=====
Spell::Spell()
{
  currPower = basePower;
  currToughness = baseToughness;
  classType = new char[strlen("Spell") + 1];
  classType = "Spell";

}

Spell::~Spell(){}

     // ---------------
Spell::Spell(const Spell & to_copy){
  currPower = to_copy.currPower;
  basePower = to_copy.basePower;
  currToughness = to_copy.currToughness;
  baseToughness = to_copy.baseToughness;
}

// =========
int Spell::attack( Spell *& blocker ){
  blocker->currToughness -= currPower;
  currToughness -= blocker->currToughness;
}

//==========
int Spell::counter (Spell *& to_counter){
  cout << to_counter->name << " was countered by " << name << endl;
}

// ============
int Spell::heal (Spell *& to_heal, int amountOfHealth){
  to_heal->currToughness += amountOfHealth;
}

// -------
Creature::Creature(){
 summoningSick = true;
}

// =====DECL======

Land::Land(){
  color = NON;
  classType = new char[strlen("Land") + 1];
  classType = "Land";
}

// ------

int Land::generateMana(int mana){
  // ... //  
}

card.h

#ifndef CARD_H
#define CARD_H
#include <cctype>
#include <iostream>
#include "conception.h"

class Artifact;
class Spell;


class Card : public Conception
{
  public:
   Card(); 
   Card(const Card &); 
  ~Card();

  protected:
    char* name;
    enum CardType { INSTANT, CREATURE, LAND, ENCHANTMENT, ARTIFACT, PLANESWALKER}; 
    enum CardColor { WHITE, BLUE, BLACK, RED, GREEN, NON };
    CardType type;
    CardColor color; 
    int manaCost;
    char* abilities;
    char* flavorText;
    char* keywords;
    bool inPlay;
    bool tapped;
    bool cursed;
    bool enchanted;
    Artifact* artifact;

    virtual int enchant( Card * );
    virtual int disenchant (Card * );
    virtual int equipArtifact(  Artifact*  );
    virtual Artifact* unequipArtifact(Card * );   
};

// ------------
class Spell: public Card
{
  public:
    Spell(); 
   ~Spell();
   Spell(const Spell &); 

  protected:
    virtual int heal( Spell *&, int );   
    virtual int attack( Spell *& );
    virtual int counter( Spell*& );
    int currToughness;
    int baseToughness;
    int currPower;
    int basePower;
};

class Land: public Card
{
  public:
    Land();
    ~Land();

  protected:
  virtual int generateMana(int);

};

class Forest: public Land
{
  public:
    Forest();
    ~Forest();

  protected:
    int generateMana();

};

class Creature: public Spell
{
  public:
    Creature();
    ~Creature();

  protected:
    bool summoningSick;

};

class Sorcery: public Spell
{
  public:
    Sorcery();
    ~Sorcery();

  protected:

};

#endif

conception.h - 这是一个“超级课程”,一切都来自

 class Conception{
  public:
    Conception(); 
    ~Conception();
  protected:
    char* classType;
};

conception.cpp

Conception::Conception{
  Conception(){
    classType = new char[11];
    char = "Conception"; 
}

game.cpp - 这是此代码中不完整的类

#include <iostream>
#include <cctype>
#include "game.h"
#include "player.h"

Battlefield::Battlefield(){
  card = 0;  
}

Battlefield::~Battlefield(){
  delete card;
}

Battlefield::Battlefield(const Battlefield & to_copy){  
}

// ===========

/*
class Game(){
  public:
    Game();
    ~Game();

  protected:
    Player** player;    // for multiple players
    Battlefield* root;  // for battlefield
    getPlayerMove();    // ask player what to do
    addToBattlefield();
    removeFromBattlefield();
    sendAttack();
}
*/

#endif

game.h

#ifndef GAME_H
#define GAME_H
#include "list.h"

class CardList();

class Battlefield : CardList{
  public:
    Battlefield();
    ~Battlefield();

  protected:
    Card* card;         // make an array
};

class Game : Conception{
  public:
    Game();
    ~Game();

  protected:
    Player** player;    // for multiple players
    Battlefield* root;  // for battlefield
    getPlayerMove();    // ask player what to do
    addToBattlefield();
    removeFromBattlefield();
    sendAttack();

    Battlefield* field;
};

list.cpp

#include <iostream>
#include <cctype>
#include "list.h"

// ==========
LinkedList::LinkedList(){
  root = new Node;
  classType = new char[strlen("LinkedList") + 1];
  classType = "LinkedList";
};

LinkedList::~LinkedList(){
  delete root;
}

LinkedList::LinkedList(const LinkedList & obj)
{
    // code to copy
}

// ---------

// =========
int LinkedList::delete_all(Node* root){
  if (root = 0)
    return 0;
  delete_all(root->next);
  root = 0;
}

int LinkedList::add( Conception*& is){
  if (root == 0){
    root = new Node;
    root->next = 0;
  }
  else
  {
    Node * curr = root;
    root = new Node;
    root->next=curr;  
    root->it = is;
  }
}

int LinkedList::remove(Node * root, Node * prev, Conception* is){
  if (root = 0)
    return -1;
  if (root->it == is){
    root->next = root->next;
    return 0;
  }
  remove(root->next, root, is);
  return 0;
}

Conception* LinkedList::find(Node*& root, const Conception* is, Conception* holder = NULL)
{
  if (root==0)
    return NULL;
  if (root->it == is){
     return root-> it;
  }
  holder = find(root->next, is);
  return holder;
}



Node* LinkedList::goForward(Node * root){
  if (root==0)
    return root;
  if (root->next == 0)
    return root;
  else
    return root->next;
} 

// ============
Node* LinkedList::goBackward(Node * root){
  root = root->prev;
}

list.h

#ifndef LIST_H
#define LIST_H
#include <iostream>
#include "conception.h"

class Node : public Conception {
  public:
    Node() : next(0), prev(0), it(0)
      { it = 0;
        classType = new char[strlen("Node") + 1];
        classType = "Node";
      };
    ~Node(){
      delete it;
      delete next;
      delete prev;
    }

    Node* next;   
    Node* prev; 
    Conception* it;                 // generic object

};

// ----------------------
class LinkedList : public Conception {
  public:
   LinkedList();
   ~LinkedList();
   LinkedList(const LinkedList&);

   friend bool operator== (Conception& thing_1, Conception& thing_2 );

  protected:
   virtual int delete_all(Node*);
   virtual int add( Conception*& );     // 
   virtual Conception* find(Node *&, const Conception*, Conception* );  //   
   virtual int remove( Node *, Node *, Conception* );   // removes  question with keyword   int display_all(node*& );               
   virtual Node* goForward(Node *);
   virtual Node* goBackward(Node *);

   Node* root;
// write copy constrcutor

};

// =============

class CircularLinkedList : public LinkedList {
  public:
   // CircularLinkedList();
   // ~CircularLinkedList();    
   // CircularLinkedList(const CircularLinkedList &);

};

class DoubleLinkedList : public LinkedList {
  public:
//    DoubleLinkedList();
  //  ~DoubleLinkedList();
  //  DoubleLinkedList(const DoubleLinkedList &);

  protected:
};

// END OF LIST Hierarchy


#endif

player.cpp

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


Library::Library(){
  root = 0;
}
Library::~Library(){
  delete card;
}

// ====DECL=========
Player::~Player(){
  delete fname;
  delete lname;
  delete deck;
}

Wizard::~Wizard(){
  delete mana;
  delete rootL;
  delete rootH;
}


// =====Player======
void Player::changeName(const char[] first, const char[] last){
  char* backup1 = new char[strlen(fname) + 1];
  strcpy(backup1, fname); 
  char* backup2 = new char[strlen(lname) + 1];
  strcpy(backup1, lname); 

  if (first != NULL){
    fname = new char[strlen(first) +1];
    strcpy(fname, first);
  }
  if (last != NULL){
    lname = new char[strlen(last) +1];
    strcpy(lname, last);
  }
  return 0;
}

// ==========
void Player::seeStats(Stats*& to_put){
  to_put->wins = stats->wins;
  to_put->losses = stats->losses;
  to_put->winRatio = stats->winRatio;
}
    // ----------

void Player::displayDeck(const LinkedList* deck){

}

// ================
void CardList::findCard(Node* root, int id, NodeCard*& is){
  if (root == NULL)
    return;
  if (root->it.id == id){
    copyCard(root->it, is);
    return;
  }
  else
    findCard(root->next, id, is);
}

     // --------
void CardList::deleteAll(Node* root){
  if (root == NULL)
    return;
  deleteAll(root->next);
  root->next = NULL;
}

    // ---------
void CardList::removeCard(Node* root, int id){
  if (root == NULL)
    return;
  if (root->id = id){
    root->prev->next = root->next;      // the prev link of root, looks back to next of prev node, and sets to where root next is pointing
  }
   return;
}

// ---------
void CardList::addCard(Card* to_add){
  if (!root){
    root = new Node;
    root->next = NULL;
    root->prev = NULL;
    root->it = &to_add;
    return;
  }
  else
  {
    Node* original = root;
    root = new Node;
    root->next = original;
    root->prev = NULL;
    original->prev = root;
  }
}

// -----------
void CardList::displayAll(Node*& root){
  if (root == NULL)
    return;

   cout << "Card Name: " << root->it.cardName;
   cout << " || Type: " << root->it.type <<  endl;
   cout << "    --------------- " << endl;
  if (root->classType == "Spell"){
    cout << "Base Power: " << root->it.basePower;
    cout << " || Current Power: " << root->it.currPower <<  endl;
   cout << "Base Toughness: " << root->it.baseToughness;
   cout << " || Current Toughness: " << root->it.currToughness <<  endl;
  }
   cout << "Card Type: " << root->it.currPower;
   cout << " || Card Color: " << root->it.color << endl;
   cout << "Mana Cost" << root->it.manaCost << endl;
   cout << "Keywords: " << root->it.keywords << endl;
   cout << "Flavor Text: " << root->it.flavorText << endl;
   cout << "  ----- Class Type: " << root->it.classType << " || ID: " << root->it.id << " -----  " << endl;
   cout << "     ******************************************" << endl;
   cout << endl;

// -------
void CardList::copyCard(const Card& to_get,  Card& put_to){
  put_to.type = to_get.type;
  put_to.color = to_get.color;
  put_to.manaCost = to_get.manaCost;
  put_to.inPlay = to_get.inPlay;
  put_to.tapped = to_get.tapped;
  put_to.class = to_get.class;
  put_to.id = to_get.id;
  put_to.enchanted = to_get.enchanted;
  put_to.artifact = to_get.artifact;  
  put_to.class = to_get.class;

  put.to.abilities = new char[strlen(to_get.abilities) +1];
  strcpy(put_to.abilities, to_get.abilities);
  put.to.keywords = new char[strlen(to_get.keywords) +1];
  strcpy(put_to.keywords, to_get.keywords);
  put.to.flavorText = new char[strlen(to_get.flavorText) +1];
  strcpy(put_to.flavorText, to_get.flavorText);

  if (to_get.class = "Spell"){
    put_to.baseToughness = to_get.baseToughness;
    put_to.basePower = to_get.basePower;
    put_to.currToughness = to_get.currToughness;
    put_to.currPower = to_get.currPower;
  }

}

 // ----------

player.h

#ifndef player.h
#define player.h

#include "list.h"

// ============
class CardList() : public LinkedList(){
  public:
    CardList();
    ~CardList();

  protected:
    virtual void findCard(Card&);
    virtual void addCard(Card* );
    virtual void removeCard(Node* root, int id);
    virtual void deleteAll();
    virtual void displayAll();
    virtual void copyCard(const Conception*, Node*&);

    Node* root;
}

// ---------
class Library() : public CardList(){
  public:
    Library();
    ~Library();

  protected:
    Card* card;
    int numCards;
    findCard(Card&);    // get Card and fill empty template
} 
  // -----------

class Deck() : public CardList(){
  public:
    Deck();
    ~Deck();

  protected:
    enum deckColor { WHITE, BLUE, BLACK, RED, GREEN, MIXED };
    char* deckName;


}

// ===============
class Mana(int amount) : public Conception {
  public:
    Mana() : displayTotal(0), classType(0) 
       { displayTotal = 0;
           classType = new char[strlen("Mana") + 1];
           classType = "Mana";
        }; 
  protected: 
    int accrued;    
    void add();
    void remove();
    int displayTotal();

}

inline Mana::add(){   accrued += 1;   }
inline Mana::remove(){  accrued -= 1; }
inline Mana::displayTotal(){  return accrued; }

// ================
class Stats() : public Conception {
  public:
    friend class Player;
    friend class Game;

    Stats() : wins(0), losses(0), winRatio(0) {
             wins = 0; losses = 0; 
             if ( (wins + losses != 0)
               winRatio = wins / (wins + losses);
             else
               winRatio = 0;
           classType = new char[strlen("Stats") + 1];
           classType = "Stats";

            }
  protected:
    int wins;
    int losses;
    float winRatio;
    void int getStats(Stats*& );
}

// ==================
class Player() : public Conception{
  public:
    Player() : wins(0), losses(0), winRatio(0) {
      fname = NULL;
      lname = NULL;
      stats = NULL;
      CardList = NULL;
      classType = new char[strlen("Player") + 1];
      classType = "Player";
    };
    ~Player();
    Player(const Player & obj);

  protected:
  // member variables
    char* fname;
    char* lname;
    Stats stats;            // holds previous game statistics    
    CardList* deck[];       // hold multiple decks that player might use - put ll in this

  private:
  // member functions
    void changeName(const char[], const char[]);
    void shuffleDeck(int);
    void seeStats(Stats*& );
    void displayDeck(int);    
    chooseDeck();
}

// --------------------
class Wizard(Card) : public Player(){
  public:
    Wizard() : { mana = NULL; rootL = NULL; rootH = NULL};
    ~Wizard();

  protected:

    playCard(const Card &);
    removeCard(Card &);
    attackWithCard(Card &);
    enchantWithCard(Card &);
    disenchantWithCard(Card &);
    healWithCard(Card &);
    equipWithCard(Card &);
    Mana* mana[];
    Library* rootL;         // Library  
    Library* rootH;         // Hand
}

#endif

1 个答案:

答案 0 :(得分:3)

至少有一个问题是&#34; player.h&#34;你有

#ifndef player.h
#define player.h

&#34; player.h&#34;不是合法的预处理器符号。你的意思是

#ifndef player_h
#define player_h

其次,conception.cpp并不包含任何内容。

第三,你的班级定义在很大程度上是无效的。

class Foo()

不合法,也不是

class Foo() : public class Bar()

&#39;()&#39;与班级名称有关?你在想构造函数吗?

然后有这个

 char = "Conception"; 

您无法为某个类型分配值。

-----反馈以帮助您清理代码-----

即可。选择一种风格

或者 - 如果您正在使用其他人的代码,请带上他们的代码。

但坚持下去。

很大比例的软件缺陷使其经历了最初的开发,因为它们很难发现 - 缺少分号,缺少复合语句等等。 &#34; CARD_H&#34; vs&#34; player.h&#34;。

即可。不一致是大多数错误的母亲

classType = new char[11];
char = "Conception"; 

你可能意味着

classType = new char[11];
classType = "Conception";

但这是内存泄漏和等待发生的错误。在Card ::你做得更准确

name = new char[strlen(to_copy.name) +1];         // creating dynamic array
strcpy(to_copy.name, name);

您在其他地方使用的版本

classType = new ...
classType = "String";

分配一些内存,将地址存储在classType中。然后它查找已编译的char *数组的变量&#34; String \ 0&#34;并将其地址存储在classType中。

当班级消失时,它会尝试删除静态字符串并崩溃。

如果这是一个学习练习,并且您正在尝试学习内存管理,那么这种一般方法可能是公平的。但是像这样在你的类中放置指针的所有权是结束内存泄漏和未定义的行为错误的可靠方法。

最好将指针封装在RAII样式的类中(一个拥有指针的类,当它超出范围时执行删除)。看看&#34; std :: unique_ptr&#34;,&#34; std :: shared_ptr&#34;和&#34; std :: weak_ptr&#34;。为了您的目的,&#34; std :: string&#34;通过消除大量的管理开销,可以帮助您减少缺陷数量。

即可。尽量避免将初始化列表与分配列表混合使用。

使用其中一种通常更好。当所有成员都可以通过这种方式进行初始化时,您可以使用初始化程序列表,但如果不能,则最好使用赋值。

Foo() : m_a(), m_b(), m_c() { m_b = 1; m_c = 2; } // is m_a not having a value a bug or intentional?

即可。区分成员变量与普通变量。

你会遇到因阴影导致价值消失的错误:Shadowing variables

#include <iostream>
int i = 0;
int main() {
    int i = 1;
    for (int i = 0; i < 10; ++i) {
        int i = 2 * i;
        std::cout << i << std::endl;
    }
    return 0;
}

当你没有区分你的成员变量时(很多人使用&#34; m _&#34;前缀,其他人使用&#34; _&#34;后缀)这就要发生了你经常。

即可。不要为指针分配数值。

name = 0;

在编译时,你会为不那么明显的数字和糟糕事物的情况做好准备。

abilities = 0;

不,我是超人,我有各种能力。

abilities = 42;

另外两种正确的方法是

name = NULL; // Traditional C++

name = nullptr; // C++11

你已经在某些地方完成了这项工作,再一致性就是失败了。

即可。 (小的,但它会在几周后咬你的屁股)&#34;它&#34;通常用于引用&#34;迭代器&#34;,您可能想要使用&#34;数据&#34;或&#34;价值&#34;或&#34;元素&#34;。

即可。避免将类/对象的成员公开。

你的节点&#34; class看起来非常错误(析构函数删除了prev和next ???)并且你不能通过查看课程来告诉他们&#34;它&#34;指针得到设置,大概是因为这发生在其他地方。你还在哪里篡改&#34;它&#34;,prev和next指针?封装

即可。 &#39; const的&#39;可以成为你的朋友(通过你的屁股痛苦)

if(to_get.class =&#34; Spell&#34;){

这将分配&#34;拼写&#34; to to_get.class,导致内存泄漏等问题,然后成功 - &#34; Spell&#34;求值为固定的const char *地址,该地址为非零,因此为真。

(它也没有编译,因为&#39; class&#39;是关键字而实际变量是&#39; className&#39;)。

您可以通过保护您的实际成员并仅通过精心挑选的访问者公开它们来防止这种情况发生。

const char* Class() const { return m_className; }

让我打破这个:

const char*   :- you cannot modify the contents,
Class()       :- instead of to_get.class you'll use to_get.Class()
const         :- this function does not have side-effects on the object

最后一部分意味着它可以在const对象上使用。

class Beer {
    bool m_isFull;
public:
    Beer() : m_isFull(true) {}

    // non-const function, has side-effects (changes isFull);
    void drink() { m_isFull = false; }

    // const function, returns a copy of "m_isFull". you can
    // change the value that's returned, but it doesn't affect us.
    void isFull() const { return m_isFull; }

    // example of a non-const accessor, if you REALLY want
    // the caller to be able to modify m_isFull for some reason.
    const bool& getIsFull() { return m_isFull; }
};

即可。最后:学习分离概念和算法。

代码中的许多错误/错误/错误似乎是因为您不是100%有一些细微差别甚至细节。这不是没有道理的,但你需要找到一种方法来尝试一些语言。

花一点时间学习在像ideone.com这样的东西上推出微程序。如果您使用的是Linux,请自己做一个&#34; srctest&#34;带有&#34; test.cpp&#34;的目录和&#34; test.h&#34;和一个Makefile

生成文件

all: srctest

srctest: srctest.cpp srctestextern.cpp srctest.h
    g++ -o srctest -Wall -ggdb srctest.cpp srctestextern.cpp

srctest.cpp

#include "srctest.h"
#include <iostream>
// add your other includes here and just leave them.

int main() {


    return 0;
}

srctest.h

#ifndef SRCTEST_SRCTEST_H
#define SRCTEST_SRCTEST_H

// anything I want to test in a .h file here

#endif

srctestextern.cpp

#include "srctest.h"

// Anything you want to test having in a separate source file goes here.

如果您正在使用visual studio,请为自己设置类似的内容。

我的想法是让你可以去一些代码,然后通过你在调试器中尝试的东西来轻松地步进。

能够快速本地化问题是成为一名成功的程序员的关键部分,而不是成为一名受雇的代码猴。