如何解决即使使用包含保护也会出现多个定义错误
我的任务是在将代码分解为多个文件时保持循环依赖,代码是关于使用面向对象的台球模拟,但我的问题不是代码而是编译。
我已经解决了这个问题,并使用这篇文章解决了我的问题:Resolve build errors due to circular dependency amongst classes
但是在“make”命令之后我不断收到编译错误,该命令说我已经多次定义了一些东西;这是虽然我使用了包含守卫来阻止程序多次包含定义,但我不知何故觉得我在某处犯了一个小错误,我似乎没有找到它。
这些是我的文件
ball.cpp
#ifndef BALL_CPP
#define BALL_CPP
#include "ball.hpp"
#include <iostream>
using namespace std;
Ball::Ball(double _x,double _y,double _vx,double _vy,Table *t)
{
cout << "Ball constructor called" << endl;
table = t;
set_location(_x,_y);
set_speed(_vx,_vy);
cout << "Initial position is: (" << x << ',' << y << ')' << endl;
}
void Ball::set_location(double _x,double _y)
{
cout << "Ball::set_location called with (" << _x << ',' << _y << ')' << endl;
if (!table->contains_point(_x,_y))
abort();
x = _x;
y = _y;
}
void Ball::set_speed(double _vx,double _vy)
{
cout << "Ball::set_speed called with (" << _vx << ',' << _vy << ')' << endl;
vx = _vx;
vy = _vy;
}
void Ball::move(double dt)
{
cout << "Ball::move called" << endl;
x += vx * dt;
y += vy * dt;
if (!table->contains_point(x,y))
table->reflect(this);
cout << "New position is: (" << x << ',' << y << ')' << endl;
}
#endif
ball.hpp
#ifndef BALL_HPP
#define BALL_HPP
#include "table.hpp"
class Ball
{
public:
Ball(double _x,Table *t);
void move(double dt);
double get_x() { return x; }
double get_y() { return y; }
double get_vx() { return vx; }
double get_vy() { return vy; }
void set_location(double _x,double _y);
void set_speed(double _vx,double _vy);
private:
double x;
double y;
double vx;
double vy;
Table *table;
};
#endif
table.cpp:
#ifndef TABLE1CPP
#define TABLE1CPP
using namespace std;
#include <iostream>
#include "ball.hpp"
Table::Table(double w,double h)
{
cout << "Table constructor called" << endl;
if (w <= 0 || h <= 0)
abort();
width = w;
height = h;
}
bool Table::contains_point(double x,double y)
{
cout << "Table::contains_point called" << endl;
return x >= 0 && x < width && y >= 0 && y < height;
}
void Table::reflect(Ball *b)
{
cout << "Table::reflect called" << endl;
double x = b->get_x();
double y = b->get_y();
double vx = b->get_vx();
double vy = b->get_vy();
while (!contains_point(x,y))
{
if (x < 0)
{
x = -x;
vx = -vx;
}
if (x >= width)
{
x = 2 * width - x;
vx = -vx;
}
if (y < 0)
{
y = -y;
vy = -vy;
}
if (y >= height)
{
y = 2 * height - y;
vy = -vy;
}
}
b->set_location(x,y);
b->set_speed(vx,vy);
}
#endif
table.hpp:
#ifndef TABLE_HPP
#define TABLE_HPP
class Ball;
class Table
{
public:
Table(double w,double h);
bool contains_point(double x,double y);
void reflect(Ball *b);
private:
double width;
double height;
};
#endif
我的makefile看起来像这样:(我对多文件概念很陌生而且非常缺乏经验,所以我可能在这里有一个我不明白的错误)
生成文件:
output: main.o table.o ball.o
g++ main.o ball.o table.o -o billiards
main.o: main.cpp
g++ -c main.cpp
ball1.o: ball.cpp ball.hpp
g++ -c ball1.cpp
table1.o: table.cpp table.hpp
g++ -c table.cpp
clean:
rm * .o output
main.cpp :
#include <iostream>
#include <cstdlib>
#include "ball.cpp" // should be changed to "ball.hpp"
#include "table.cpp" // should be changed to "table.hpp"
using namespace std;
int main()
{
Table t(100,50);
Ball b(10,20,25,5,&t);
b.move(10);
}
错误:
/usr/bin/ld: ball.o: in function `Ball::Ball(double,double,Table*)':
ball.cpp:(.text+0x0): multiple definition of `Ball::Ball(double,Table*)'; main.o:main.cpp:(.text+0x0): first defined here
/usr/bin/ld: ball.o: in function `Ball::set_location(double,double)':
ball.cpp:(.text+0x10c): multiple definition of `Ball::set_location(double,double)'; main.o:main.cpp:(.text+0x10c): first defined here
/usr/bin/ld: ball.o: in function `Ball::set_speed(double,double)':
ball.cpp:(.text+0x1dc): multiple definition of `Ball::set_speed(double,double)'; main.o:main.cpp:(.text+0x1dc): first defined here
/usr/bin/ld: ball.o: in function `Ball::Ball(double,Table*)'; main.o:main.cpp:(.text+0x0): first defined here
/usr/bin/ld: ball.o: in function `Ball::move(double)':
ball.cpp:(.text+0x280): multiple definition of `Ball::move(double)'; main.o:main.cpp:(.text+0x280): first defined here
/usr/bin/ld: table.o: in function `Table::Table(double,double)':
table.cpp:(.text+0x0): multiple definition of `Table::Table(double,double)'; main.o:main.cpp:(.text+0x3be): first defined here
/usr/bin/ld: table.o: in function `Table::Table(double,double)'; main.o:main.cpp:(.text+0x3be): first defined here
/usr/bin/ld: table.o: in function `Table::contains_point(double,double)':
table.cpp:(.text+0x7c): multiple definition of `Table::contains_point(double,double)'; main.o:main.cpp:(.text+0x43a): first defined here
/usr/bin/ld: table.o: in function `Table::reflect(Ball*)':
table.cpp:(.text+0x10a): multiple definition of `Table::reflect(Ball*)'; main.o:main.cpp:(.text+0x4c8): first defined here
collect2: error: ld returned 1 exit status
make: *** [Makefile:2: output] Error 1
解决方法
好的,这就是正在发生的事情:main.cpp
正在拉动 ball.cpp
和 table.cpp
,因此目标文件 main.o
将具有所有函数和您在 ball.cpp
和 table.cpp
中实现的变量。
这是一个问题,因为您还单独编译 ball.cpp
和 table.cpp
,因此您最终会得到所有重复。
我猜您将包含守卫放在 .cpp 文件中是为了避免这个问题,但是,这实际上不起作用:#define
的宏不会在编译器的调用之间延续。
您在这里要做的是 #include
.hpp 文件:main.cpp
将能够看到您正在使用的功能的声明,但是不会将实现编译为 main.o
,因此不会与 ball.o
或 table.o
发生任何冲突。
此外,您可能应该从 .cpp 文件中删除包含守卫:正是由于这些重复的原因,通常不会对 C 或 C++ 源文件进行 #include
ing与您的特定情况相关。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。