C ++方法错误的多重定义;学习继承

时间:2014-06-01 16:14:32

标签: c++

大家好,这是我在堆栈上的第一篇文章。我正在从一本书中学习C ++" C ++编程为绝对的初学者"马克李。我正在通过制作关于龙的游戏来学习继承。我知道它的良好实践是为定义创建一个头文件,并为实现创建一个cpp文件。但是,我按照那个人在书中写的内容,并在同一个文件中定义并编写了实现.cpp(我相信在c ++中仍然可以正确吗?)。无论如何,在完成它并尝试编译后我得到了

  

Dragon :: attack(int)的多重定义

这个错误几乎出现在所有方法中。弹出没有链接器错误。对不起,如果我的解释持续很长时间。这是文件。提前谢谢,如果可能的话,我可以按照它们在同一文件中的定义和实现的方式保留类。

  

Dragon.cpp

#pragma once
#include<string>
#include<ctime>
#include<cstdlib>

using std::string;
#define MAX(a,b) a>b? a:b

class Dragon
{
      private:
              int speed;
              string name;
              int hitPoints;
              int armor;
              int treasure;
              int clawDamage;
              int size;
      protected:
                Dragon(int theSize);
                int getArmor(){return armor;}
                 int& getHitPoints(){return hitPoints;}
                int getClawDamage(){return clawDamage;}
               int getSize() {return size;}
                virtual int attack(int targetArmor, int specialDamage);
     public:
            virtual int attack(int targetArmor)=0;
            virtual void defend(int damage)=0;
     int getTreasure(){return treasure;}
           virtual string getName(){return name;}
             int getSpeed(){return speed;}
           bool isAlive(){return hitPoints>0;}
};

 Dragon::Dragon(int theSize): size(theSize)
{
          if (size<1||size >4)
            size=3;
     clawDamage=2*size;
     speed=2*size;
     hitPoints=4*size;
     armor=size;
     treasure=1000*size;
     srand(time(0));
}
 int Dragon::attack(int targetArmor, int specialDamage)
{
        int useSpecial=rand()%2; //0 or 1
        int damage;
        if(useSpecial)
        damage=specialDamage;
         else 
         damage=getClawDamage();
         return MAX(damage-targetArmor,0);
}      
  

BlackDragon.cpp

#include<string>
#include"Dragon.cpp"

using std::string;

class BlackDragon : public Dragon
{
      private:
              int poisonDamage;
      public:
             BlackDragon(int theSize);
             int attack(int targetArmor);
             void defend(int damage);
             string getName(){return "Black Dragon";}
};

BlackDragon::BlackDragon(int theSize):Dragon(theSize)
{
     poisonDamage=getSize();
}
int BlackDragon::attack(int targetArmor)
{
    return Dragon::attack(targetArmor, poisonDamage);
}
void BlackDragon::defend(int damage)
{
    getHitPoints()-=damage - getArmor();
}
  

RedDragon.cpp

#include<string>
#include"Dragon.cpp"

using std::string;

class RedDragon : public Dragon
 {
      private:
              int fireDamage;
      public:
             RedDragon(int theSize);
             int attack(int targetArmor);
             void defend(int damage);
             string getName(){return "Red Dragon";}
};
RedDragon::RedDragon(int theSize):Dragon(theSize)
{
            fireDamage=4*getSize();
}
int RedDragon::attack(int targetArmor)
{
    return Dragon::attack(targetArmor, fireDamage);
}
void RedDragon::defend(int damage)
{
     getHitPoints()-=(damage-getArmor())/3;
}
  

BlueDragon.cpp

#include<string>
#include"Dragon.cpp"

using std::string;

class BlueDragon: public Dragon
{
      private:
              int iceDamage;
      public:
             BlueDragon(int theSize);
             int attack(int targetArmor);
             void defend(int damage);
             string getName(){return "Blue Dragon";}
};
BlueDragon::BlueDragon(int theSize):Dragon(theSize)
{
            iceDamage=3*getSize();
}

int BlueDragon::attack(int targetArmor)
{
    return Dragon::attack(targetArmor, iceDamage);
}
void BlueDragon::defend(int damage)
{
     getHitPoints()-=(damage-getArmor())/2;
}
  

DragonLord.cpp

#include<iostream>
#include<ctime>
#include<cstdlib>
#include "Dragon.cpp"
#include "RedDragon.cpp"
#include "BlueDragon.cpp"
#include "BlackDragon.cpp"

int menuChoice();

int main(void)
{
    using std::srand;
    using std::time;
    using std::rand;
    using std::cout;
    srand((unsigned int)time(0));
    Dragon* dragons[3];
    int hp=15;
    int armor=2;
    int tempArmor;
    int tempAttack;
    dragons[0]=new RedDragon(rand()%4+1);
    dragons[1]=new BlackDragon(rand()%4+1);
    dragons[2]=new BlueDragon(rand()%4+1);
    Dragon* d=dragons[rand()%3];
    cout<<"Welcome noble knight. \n"
    <<"You must save a princess."
    <<"She has been captured by a "
    <<d->getName()<<"\n"
    <<"You must defeat the dragon. \n";
    cout<<"Your hit points are: "<<hp<<"\n";
   while(d->isAlive()&&hp>0)
    {
        int choice=menuChoice();
    if(choice==3)
         goto RUN;
      else if(choice==1)
      {
           tempAttack=rand()%16+5;
           tempArmor=armor;
      }
      else
      {
          tempAttack=rand()%11;
          tempArmor=armor+4;
      }
      hp-=d->attack(armor);
      d->defend(rand()%16-5);
      cout<<"\nYou deliver a mighty blow and deel "<<tempAttack
      <<" damage. \n";
      cout<<"Your hit points are: "<<hp;
      }
      if(d->isAlive())
      cout<<"\nYou have perished before"
      <<" the might of the dragon.\n";
      else 
      cout<<"\n\nYou ahve slain the dragon!"
      <<"Congratulations.\n"
      <<"the Princess is saved. \n";
      return 0;
      RUN:
          cout<<"\nYou ahve fled in cowardice.\n";
          return 0;
}

int menuChoice()
{
    using std::cout;
    using std::cin;
    int choice;
    do{
        cout<<"\n[1]Atack\n"
        <<"[2]Defensive Mode\n"
        <<"[3]Run Away\n";
        cin>>choice;
      }while(choice<1&& choice>3);
      return choice;
}

2 个答案:

答案 0 :(得分:1)

您正在 .cpp 文件中定义类并多次包含它们。例如,当您在 BlackDragon.cpp BlackDragon.cpp 中包含 Dragon.cpp 时,{{>>中的所有内容都会有两个定义。 1}}类。这将导致此问题(中断One Definition Rule)。

有一些方法可以避免这种情况,但在 C ++ 中,最常见且最简单的做法是在标题(.h)文件中声明您的类并实现< em> .cpp 文件。如果另一个需要一个类定义,那么请包含 .h 文件。

你可以这样做:

Dragon

然后继承类

//Dragon.h
class Dragon
{
  private:
          int speed;
          string name;
          int hitPoints;
          int armor;
  /// other variables and methods
}

//Dragon.cpp
 #include"Dragon.h"


//implement methods

答案 1 :(得分:0)

你包括&#34; .cpp&#34;文件。这是一个非常糟糕的主意。实际上,您应该在头文件中定义类并在cpp文件中实现它们。这样,您就不会暴露您的实现,只暴露您的界面,并且每个符号只会被编译一次。这应该可以解决你的问题。

此外,您可能希望在头文件中实现方法,例如在创建模板类时,但是您不应该包含任何不是标题的内容。

您的书似乎有点过时,使用宏而不是std :: max等。你可能应该拿一本关于C ++ 11的新的,有光泽的书。