大家好,这是我在堆栈上的第一篇文章。我正在从一本书中学习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;
}
答案 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的新的,有光泽的书。