-3

我完全束手无策:我无法弄清楚我的依赖问题是如何出现的。我已经阅读了无数的帖子和博客,并且多次修改我的代码,以至于我什至不记得什么几乎可以工作,什么没有。我不仅不断收到重新定义错误,而且还收到类未定义错误。我重新设计了标题保护并删除了一些错误,只是为了找到其他错误。我不知何故把一切都归结为一个错误,但在试图修复它时,即使它也坏了。

你能帮我找出问题吗?

卡片.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){
  // ... //  
}

卡.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;
};

概念.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

游戏.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;
};

列表.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;
}

列表.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

播放器.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;
  }

}

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

播放器.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
4

1 回答 1

3

至少你的一个问题是在“player.h”中你有

#ifndef player.h
#define player.h

“player.h”不是合法的预处理器符号。你的意思

#ifndef player_h
#define player_h

?

其次,conception.cpp 没有#include 任何东西。

第三,您的类定义在很大程度上是无效的。

class Foo()

不合法,也不合法

class Foo() : public class Bar()

'()' 与类名有什么关系?你在考虑构造函数吗?

然后有这个

 char = "Conception"; 

您不能为类型分配值。

----- 反馈帮你清理代码 -----

. 选择一种风格

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

但坚持下去。

很大比例的软件缺陷导致它通过初始开发,因为它们很难发现 - 缺少分号,缺少复合语句周围的 {s 等。参见“CARD_H”与“player.h”。

. 不一致是大多数错误的根源

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* 数组“String\0”的变量,并将其地址存储在 classType 中。

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

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

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

. 尽量避免将初始化列表与赋值列表混合。

通常最好使用其中一种。当您的所有成员都可以通过这种方式初始化时,您可能可以摆脱使用初始化列表,但如果他们不能,使用赋值可能会更好。

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

. 区分成员变量和普通变量。

您将遇到由于阴影而导致值消失的错误:阴影变量

#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;
}

当你不区分你的成员变量时(很多人使用“m_”前缀,其他人使用“_”后缀)这将经常发生在你身上。

. 不要为指针分配数值。

name = 0;

在编译时,您正在为不太明显的情况做好准备,这些情况似乎是数字和随之而来的坏事。

abilities = 0;

不,我是超人,我拥有所有的能力。

abilities = 42;

另外两种正确的方法是

name = NULL; // Traditional C++

或者

name = nullptr; // C++11

您已经在某些地方做到了这一点,但一致性再次让您失望。

. (次要但几周后它会咬你的屁股)“它”通常用于引用“迭代器”,您可能想要使用“数据”或“值”或“元素”。

. 避免公开类/对象的成员。

您的“节点”类看起来非常错误(析构函数删除了 prev 和 next ???),并且您无法通过查看该类来判断“it”指针是如何设置的,大概是因为这发生在其他地方。您还在哪里篡改“it”、prev 和 next 指针?封装。

. 'const' 可以成为你的朋友(通过成为你的屁股)

if (to_get.class = "拼写"){

这会将“Spell”分配给 to_get.class,导致内存泄漏和其他问题,然后成功——“Spell”计算为一个固定的 const char* 地址,该地址非零,因此是正确的。

(它也不能编译,因为'class'是一个关键字,而实际变量是'className')。

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

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,请为自己创建一个带有“test.cpp”和“test.h”以及 Makefile 的“srctest”目录

生成文件

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.

如果您使用的是视觉工作室,请为自己设置类似的东西。

这个想法是在某个地方你可以去输入几行代码,并且可以轻松地通过你在调试器中尝试的内容。

能够快速定位问题是成为成功程序员的关键部分,而不是成为受雇的代码猴子。

于 2013-10-28T19:56:01.900 回答