我似乎无法确定这个问题,所以我想我会问这里。我知道为什么会出现这个错误,但这次我似乎无法弄明白。可能是一些我不知道或遗失的简单事。
g++ -c -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT src/Render.cpp -L/usr/lib/i386-linux-gnu -lSDL -lSDL_image
src/Render.cpp:8:1: error: ‘Render’ does not name a type
src/Render.cpp:13:1: error: ‘Render’ does not name a type
src/Render.cpp:18:14: error: ‘Render’ has not been declared
src/Render.cpp:31:6: error: ‘Render’ has not been declared
make: *** [Render.o] Error 1
这是我的core.cpp,Makefile和Render.h
Render.cpp
#ifndef _Render_h
#define _Render_h
#include <iostream>
#include "SDL/SDL_image.h"
using namespace std;
Render::Render()
{
}
Render::~Render()
{
}
SDL_Surface* Render::loadImg(string filename)
{
SDL_Surface* temp = NULL;
SDL_Surface* optimized = NULL;
if((temp = IMG_Load(filename.c_str())) != NULL)
{
optimized = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);
}
return optimized;
}
void Render::applySurface(int x, int y, SDL_Surface* source,
SDL_Surface* destination)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface(source, NULL, destination, &offset);
}
#endif
core.cpp
#include <iostream>
#include "SDL/SDL.h"
#include "Render.h"
using namespace std;
int main(int argc, char* args[])
{
string imgGoku = "src/imgs/Goku.bmp";
string imgVegeta = "src/imgs/Vegeta.png";
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
SDL_Surface *message = NULL;
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;
Render rnd;
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return 1;
}
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT,
SCREEN_BPP, SDL_SWSURFACE);
if(screen == NULL)
{
return 1;
}
SDL_WM_SetCaption("Hello World", NULL);
rnd.applySurface(10,10,rnd.loadImg(imgGoku),screen);
if(SDL_Flip(screen) == -1)
{
return 1;
}
SDL_Delay(2000);
SDL_FreeSurface(message);
SDL_FreeSurface(background);
SDL_Quit();
return 0;
}
Render.h
#include "SDL/SDL.h"
using namespace std;
class Render{
public:
Render();
~Render();
SDL_Surface* loadImg(string filename);
void applySurface(int x, int y,
SDL_Surface* source,
SDL_Surface* destination);
};
生成文件
#Game Make file
TARGET = game.exe
OBJS = core.o \
Render.o \
SDL_CFLAGS := $(shell sdl-config --cflags)
SDL_LDFLAGS := $(shell sdl-config --libs) -lSDL_image
CFLAGS = -Wall
LIBS =
LDFLAGS =
$(TARGET): $(OBJS)
g++ $(CFLAGS) $(SDL_CFLAGS) -o $@ $(LDFLAGS) $(OBJS) $(SDL_LDFLAGS) $(LIBS)
%.o: src/%.cpp src/Render.h
g++ -c $(SDL_CFLAGS) $< $(SDL_LDFLAGS)
.PHONY: clean
clean:
rm -f $(TARGET) $(OBJS)
答案 0 :(得分:3)
您需要在Render.cpp顶部包含Render.h
答案 1 :(得分:3)
烨。我认为这就是#ifndef和#define的作用,但我想我理解它们或使用它们是错误的。
你误解了他们和你错误地使用了它们。
虽然向Render.cpp文件添加#include "Render.h"
指令会修复您的即时编译问题,但它并不能解决误解和误用的双重问题。您应该对代码进行其他两个修复。我将总结你应该做出的更正,然后说明为什么要这样做。
问题#1:您需要将#ifndef _Render_h
/ #define _Render_h
对和结束#endif
从源文件移动到标题。
问题#2:从预处理器符号_Render_h
中删除前导下划线。
#include guards
查看几乎所有系统头文件,您会看到它们遵循非常标准的布局。该文件以描述该文件的标题注释开头。紧接着这是一对#ifndef _SOME_NAME_H_
和#define _SOME_NAME_H_
形式的行。文件正文如下,文件中的最后一项是结束#endif
。该#ifndef
/ #define
对称为#include
后卫。关闭#endif
总是(好吧,几乎总是;其中一些系统标题违反了标准布局)。
这样做是为了防止多次包含相同的标头。假设您有头文件foo.h,bar.h和baz.h.假设foo.h和bar.h都使用baz.h中定义的功能。这些标题中的每一个都应该具有#include "baz.h"
指令,最好在顶部附近。现在假设你的main.cpp #include
是foo.h和bar.h.如果文件baz.h没有#include
防护,它将在main.cpp中包含两次。你的main.cpp很可能无法编译。
这个多重包含问题的解决方案是将#include
保护放在文件baz.h中。现在main.cpp中的#include "foo.h"
会将baz.h的主体粘贴到您的代码中,但#include "bar.h"
不会,因为baz.h中的#include
后卫会生成预处理器跳过baz.h的主体。
最好在每个头文件中放一个#include
守卫。
#pragma一次
#include
守卫的概念有几个问题。
#ifndef
指令中,另一次在#define
指令中。这对于墨菲法则来说是一个巨大的机会,可以让它变得丑陋。程序员可以并且确实错误地输入了这些名称中的一个。#endif
是另一个潜在的问题来源。一些维护程序员(维护程序员是开发程序员存在的祸根)将会看到在关闭#endif
之后添加代码将对他的烦恼问题做出快速而肮脏的修复。维护程序员总是选择最快,最脏的解决方案。做完了。#include
进行Render_h
保护,则会出现一个巨大的问题。这些问题有一个很好的解决方案,即#pragma once
指令。如果这个pragma工作正常,它确实与#include
后卫打算做的完全相同,但更好。只有一行而不是三行,并且没有预处理器名称。问题是“如果它有效”。这是一个pragma,所以并非所有的编译器都支持它,而且一些支持它的人不能正确使用它。
由于#include
的可移植性问题,我倾向于使用#pragma once
警卫。其他人使用#pragma once
因为可移植性问题不适用于他们的项目。还有一些人使用这两种机制。
引导下划线
如果你查看一个系统头文件,你会看到它充满了带有前导下划线的名字。这可能会给人留下这样的印象:使用前导下划线是正确的做法。毕竟,谁比编译器供应商更了解语言?
编译器供应商使用前导下划线的原因是为了避免与代码冲突。一个好的编译器供应商正好使用前导下划线,因为如果你不在任何名字中使用前导下划线,这样做会使他们的名字不与你的名字发生冲突。永远不要在类的名称,全局变量,自由函数或预处理器符号中使用前导下划线。前导下划线保留供编译器使用。