显示函数重复定义怎么解决?

Mars.CN 2021-01-22 06:07:26
我在写一个C++的练习,大体结构是在.h文件中定义了几个类的结构,然后分cpp文件实现,每个类一个cpp文件。
编译的时候单个cpp文件都编译过去了。
但是最后链接的时候出现错误

/usr/bin/ld: ./debug/run.o: in function `rpf::RP_Graphics::RP_Graphics()':
graphics.cpp:(.text+0x0): multiple definition of `rpf::RP_Graphics::RP_Graphics()'; ./debug/graphics.o:graphics.cpp:(.text+0x0): first defined here

基本都是RP_Graphics类报错,每个函数都提示这个
请问这个是什么原因引起的?
是我.h和cpp文件的结构用的不对吗?
...全文
744 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
Mars.CN 2021-02-03
  • 打赏
  • 举报
回复
错误结果:
BUILD : src/graphics.cpp -> debug/graphics.o
g++ -Isrc/include -std=c++11 -lstdc++ -c src/graphics.cpp -o debug/graphics.o
BUILD : src/graphics.cpp -> debug/run.o
g++ -Isrc/include -std=c++11 -lstdc++ -c src/graphics.cpp -o debug/run.o
BUILD : src/graphics.cpp -> debug/canvas.o
g++ -Isrc/include -std=c++11 -lstdc++ -c src/graphics.cpp -o debug/canvas.o
g++ -Isrc/include ./debug/graphics.o ./debug/run.o ./debug/canvas.o -o ./debug/exec
/usr/bin/ld: ./debug/run.o: in function `rpf::Graphics::Graphics(rpf::Canvas*)':
graphics.cpp:(.text+0x0): multiple definition of `rpf::Graphics::Graphics(rpf::Canvas*)'; ./debug/graphics.o:graphics.cpp:(.text+0x0): first defined here
/usr/bin/ld: ./debug/run.o: in function `rpf::Graphics::Graphics(rpf::Canvas*)':
graphics.cpp:(.text+0x0): multiple definition of `rpf::Graphics::Graphics(rpf::Canvas*)'; ./debug/graphics.o:graphics.cpp:(.text+0x0): first defined here
/usr/bin/ld: ./debug/run.o: in function `rpf::Graphics::drawPoint(unsigned int, unsigned int)':
graphics.cpp:(.text+0x1e): multiple definition of `rpf::Graphics::drawPoint(unsigned int, unsigned int)'; ./debug/graphics.o:graphics.cpp:(.text+0x1e): first defined here
/usr/bin/ld: ./debug/canvas.o: in function `rpf::Graphics::Graphics(rpf::Canvas*)':
graphics.cpp:(.text+0x0): multiple definition of `rpf::Graphics::Graphics(rpf::Canvas*)'; ./debug/graphics.o:graphics.cpp:(.text+0x0): first defined here
/usr/bin/ld: ./debug/canvas.o: in function `rpf::Graphics::Graphics(rpf::Canvas*)':
graphics.cpp:(.text+0x0): multiple definition of `rpf::Graphics::Graphics(rpf::Canvas*)'; ./debug/graphics.o:graphics.cpp:(.text+0x0): first defined here
/usr/bin/ld: ./debug/canvas.o: in function `rpf::Graphics::drawPoint(unsigned int, unsigned int)':
graphics.cpp:(.text+0x1e): multiple definition of `rpf::Graphics::drawPoint(unsigned int, unsigned int)'; ./debug/graphics.o:graphics.cpp:(.text+0x1e): first defined here
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [Makefile:27:debug/exec] 错误 1
Mars.CN 2021-02-03
  • 打赏
  • 举报
回复
引用 9 楼 forever74 的回复:
明明是很简单的问题,楼主你非要蒙着眼睛让人玩瞎子摸象。
你过于相信自己的语言表达,事实上如果关键问题让你注意到了,那么你自己早就解决了。
所以你再怎么说,都说不到点子上。
别人猜,也很难猜到点子上。

不上代码,都是隔靴搔痒。


你说的对,虚心接受

代码太多,贴出来不方便,我做了一个简化的,问题是一样的
一共五个文件:
结构如下
test/
src/
canvas.cpp
graphics.cpp
run.cpp
include/
rpf.h
Makefile
debug/

头文件rpf.h

#ifndef __RAINBOWPIXLE_H__
#define __RAINBOWPIXLE_H__
#include <iostream>

namespace rpf
{
class Canvas;
class Graphics;

/**
* 画布类,包含Graphics
*/
class Canvas
{
private:
Graphics* graphics;

public:
Canvas();
Graphics* getGraphics();
};

/**
* 画笔类,属于Canvas
*/
class Graphics
{
private:
Canvas* canvas;
public:
void init();
Graphics(Canvas* canvas);
Graphics* drawPoint(uint32_t x, uint32_t y);
};
}


#endif // !__RAINBOWPIXLE_H__



画布文件canvas.cpp

#include "include/rpf.h"

namespace rpf
{
Canvas::Canvas()
{
this->graphics = new Graphics(this);
}

Graphics* Canvas::getGraphics()
{
return this->graphics;
}
}



画笔文件graphics.cpp

#include "include/rpf.h"

namespace rpf
{
using namespace std;

Graphics::Graphics(Canvas* canvas)
{
this->canvas = canvas;
}

Graphics* Graphics::drawPoint(uint32_t x, uint32_t y)
{
cout << "Draw a dot at " << x << " and " << y << endl;
return this;
}
}



运行测试文件run.cpp

#include "include/rpf.h"

int main(int argc, char** argv)
{
using namespace rpf;

Canvas* canvas = new Canvas();

Graphics* g = canvas->getGraphics();

g->drawPoint(100, 200)->drawPoint(30,40);

return 0;
}


Makefile文件

CC = $(CROSS_COMPILE)g++
CXX = $(CROSS_COMPILE)g++
LD = $(CROSS_COMPILE)ld
AR = $(CROSS_COMPILE)ar

CPP_SOURCES = $(wildcard ./src/*.cpp)
OUTPUT = ./debug
TARGET = $(OUTPUT)/exec
INSTALLDIR = ./
CPPOBJS = $(objects)run.o $(objects)canvas.o $(objects)graphics.o


DIR_OBJS = $(patsubst %.cpp,%.o,$(CPP_SOURCES))
OBJS_NAME = $(notdir $(patsubst %.cpp,%.o,$(CPP_SOURCES)))
OBJS = $(addprefix $(OUTPUT)/,$(notdir $(patsubst %.cpp,%.o,$(CPP_SOURCES))))

INCS =-Isrc/include

LIBS =-std=c++11 -lstdc++

CFLAGS += -O2 $(INC_DIRS)
LKFLAGS += $(LIBS)

all:$(TARGET)

$(TARGET):$(OUTPUT) $(OBJS)
$(CC) $(INCS) $(OBJS) $(LDFLAGS) -o $(TARGET)

$(OBJS):$(CPP_SOURCES)
@echo "BUILD : " $< " -> " $@
$(CC) $(INCS) $(LIBS) -c $< -o $@

distclean :
-rm $(OUTPUT)/* -f



我用了两种方式做编译,如果用
g++ -Isrc/include -std=c++11 -lstdc++ src/run.cpp src/graphics.cpp src/canvas.cpp -o exec
编译顺畅,可以执行

但是如果make就会报上面描述的那个错误
forever74 2021-02-03
  • 打赏
  • 举报
回复
被发现了。 隔靴搔痒一词,并非本人惯用语,确为近期抄袭自四老师的系列回复。
赵4老师 2021-02-03
  • 打赏
  • 举报
回复
引用 9 楼 forever74 的回复:
明明是很简单的问题,楼主你非要蒙着眼睛让人玩瞎子摸象。 你过于相信自己的语言表达,事实上如果关键问题让你注意到了,那么你自己早就解决了。 所以你再怎么说,都说不到点子上。 别人猜,也很难猜到点子上。 不上代码,都是隔靴搔痒。
不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
forever74 2021-02-03
  • 打赏
  • 举报
回复
明明是很简单的问题,楼主你非要蒙着眼睛让人玩瞎子摸象。 你过于相信自己的语言表达,事实上如果关键问题让你注意到了,那么你自己早就解决了。 所以你再怎么说,都说不到点子上。 别人猜,也很难猜到点子上。 不上代码,都是隔靴搔痒。
Mars.CN 2021-02-03
  • 打赏
  • 举报
回复
引用 7 楼 赵4老师 的回复:
你的众多cpp文件中应该有
重复
RP_Graphics::RP_Graphics();
或重复
RP_Graphics::RP_Graphics(RP_Canvas* canvas);


只有一个文件中定义了这些函数,另外就是在.h文件中声明过
当我使用
g++ -Isrc/include -std=c++11 -lstdc++ src/run.cpp src/graphics.cpp src/canvas.cpp src/image.cpp src/game.cpp -o main
这种方式编译的时候就没问题,能直接过去,main也可以运行
但是我写了个Makefile,里面是单个编译cpp文件,单独编译的时候都顺利过去
但把多个.o文件链接成可执行文件的时候就出现了这个错误。
我觉得问题应该是每个独立的.o文件中肯定有Graphics文件的引用
但是我在单独编译每个cpp的时候,已经加了-c参数
$(CC) $(INCS) $(LIBS) -c $< -o $@
-c不是独立编译的意思吗?为啥还会有包含进去的问题
Mars.CN 2021-02-03
  • 打赏
  • 举报
回复
引用 15 楼 forever74 的回复:
这样下来三个.o是相同的,重复就产生了。

看来是我Makefile写错了

不细心造成的……
多谢!
forever74 2021-02-03
  • 打赏
  • 举报
回复
这样下来三个.o是相同的,重复就产生了。
forever74 2021-02-03
  • 打赏
  • 举报
回复
看这几行,不可疑么? 两个.o生成错了。
赵4老师 2021-02-02
  • 打赏
  • 举报
回复
你的众多cpp文件中应该有 重复 RP_Graphics::RP_Graphics(); 或重复 RP_Graphics::RP_Graphics(RP_Canvas* canvas);
Mars.CN 2021-02-02
  • 打赏
  • 举报
回复
问题依然未解决
Mars.CN 2021-01-23
  • 打赏
  • 举报
回复
当然没有,头文件就是上面我贴出来的那种形式,只有定义,实现都写在cpp里面了。
不知道C++是不是这种写法,感觉非常别扭。
一方面想隐藏的私有内容没办法隐藏,都得公布到头文件
另一方面,如果想加个函数,两边都得改,太费劲了。
forever74 2021-01-22
  • 打赏
  • 举报
回复
你把那些函数的实现也写在头文件里了?
Mars.CN 2021-01-22
  • 打赏
  • 举报
回复
这个做了
我发现如果使用g++直接编译的时候没问题,只要单开编译再连接就出问题
g++ -Isrc/include -std=c++11 -lstdc++ src/run.cpp src/graphics.cpp src/canvas.cpp src/image.cpp src/game.cpp -o main
这种方式直接过
但是我用Makefile
先把.cpp编译成.o文件,用g++ -c
然后使用
g++连接
这样做肯定出问题
我把所有的类声明都写在一个.h文件中了
forever74 2021-01-22
  • 打赏
  • 举报
回复
.h文件因为会被多处引用,因而它有义务阻止自己多次发挥作用(重复定义)。 参考一下系统的.h 多半都有 #ifndef _xx_h_ #define _xx_h_ define something yourself #endif 这种结构。 模仿之。
Mars.CN 2021-01-22
  • 打赏
  • 举报
回复

namespace rpf
{
class RP_Graphics
{
private:
RP_Brush brush; // 画笔样式
RP_Canvas* canvas; // 操作的画布
public:
RP_Graphics();
RP_Graphics(RP_Canvas* canvas);
~RP_Graphics();

RP_Brush& getBrush(); // 获得画笔,获得后可直接修改

RP_Graphics drawPoint(const RP_Point& point) const; // 画点
RP_Graphics drawLine(const int size ,const RP_Point** point) const; // 划线
RP_Graphics drawRect(const RP_Rectangle& rect) const; // 绘制矩形
RP_Graphics fillRect(const RP_Rectangle& rect) const; // 绘制填充矩形
RP_Graphics drawCircle(const RP_Rectangle& rect) const; // 绘制圆形
RP_Graphics fillCircle(const RP_Point& point , const uint32_t radius) const; // 绘制圆形
RP_Graphics drawPolygon(const int size ,const RP_Point** point) const; // 绘制多边形
RP_Graphics fillPolygon(const int size ,const RP_Point** point) const; // 绘制多边形

// 绘制Canvas和Image的函数
RP_Graphics draw(RP_Canvas& canvas , const RP_Point& rect) const;
RP_Graphics draw(RP_Canvas& canvas , const RP_Rectangle& rect) const;
RP_Graphics draw(RP_Canvas& canvas , const RP_Rectangle& r_rect,const RP_Point& rect) const;
RP_Graphics draw(RP_Canvas& canvas , const RP_Rectangle& r_rect,const RP_Rectangle& d_rect) const;
};
}

这是.h文件中关于RP_Graphics的定义

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧