C++ 不命名类型错误
C++ Does not name a type error
我似乎无法指出这个问题,所以我想我会在这里问。我知道为什么通常会出现此错误,但这次我似乎无法弄清楚。可能是我不知道或缺少的简单东西。
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
这是我的核心.cpp,Makefile和Render.h
渲染.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
核心.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;
}
渲染.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)
的顶部包含 Render.h.cpp
你是的。我以为这就是 #ifndef 和 #define 所做的,但我想我理解它们或错误地使用它们。
误解了它们,你用错了它们。
虽然将 #include "Render.h"
指令添加到 Render.cpp 文件可以解决您的即时编译问题,但它不能解决误解和误用的双重问题。您应该对代码进行另外两个修复。我将总结您应该进行的更正,然后说明为什么要这样做。
问题#1:您需要将该#ifndef _Render_h
/#define _Render_h
对和结束#endif
从源文件移动到标头。
问题 #2:从预处理器符号中删除前导下划线 _Render_h
。
#include 卫士
查看几乎所有的系统头文件,您会发现它们遵循非常标准的布局。该文件以描述文件的标题注释开头。紧随其后的是一对形式为 #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"
指令,最好靠近顶部。现在假设你的主.cpp #include
s foo.h 和 bar.h。如果文件 baz.h 没有#include
保护,它将包含在您的主.cpp中两次。您的主.cpp很可能不会编译。
这个多重包含问题的解决方案是在文件 baz.h 中放置一个#include
保护。现在 main.cpp 中的#include "foo.h"
会将 baz.h 的主体粘贴到您的代码中,但#include "bar.h"
不会,因为 baz.h 中的#include
守卫会使预处理器跳过 baz.h 的主体。
在每个头文件中放置一个#include
防护。
#pragma 一次#include
卫士的概念有几个问题。
- 必须指定两次名称,一次在
#ifndef
指令中,另一次在#define
指令中。这是墨菲定律养育丑陋头颅的巨大机会。程序员可以并且确实错误地键入了这些名称中的一个或另一个。 - 最后的
#endif
是另一个潜在的问题来源。一些维护程序员(维护程序员是开发程序员存在的祸根)会看到,在关闭#endif
之后添加代码将快速而肮脏地解决他棘手的问题。维护程序员总是选择最快、最脏的解决方案。就这样完成了。 - 名称必须是唯一的。假设您只是从事大型项目的众多人员之一,并且假设您和其他人都有一个名为 Render.h 的文件。这两个文件位于两个不同的目录中,因此两个文件具有相同的名称没有问题。如果两个文件都有使用预处理器符号
Render_h
的#include
保护,则会出现一个巨大的问题。
这些问题有一个很好的解决方案,即#pragma once
指令。这种编译指示,如果它有效,完全符合#include
守卫的意图,但更好。只有一行而不是三行,并且没有预处理器名称。问题是"如果它有效"。这是一个编译指示,所以并非所有编译器都支持它,一些支持它的编译器做得不正确。
我倾向于使用#include
防护装置,因为#pragma once
的便携性问题。其他人使用#pragma once
因为可移植性问题不适用于他们的项目。还有一些人同时使用这两种机制。
前导下划线
如果您查看系统头文件,您会发现它充满了带有前导下划线的名称。这可能会给人一种印象,即使用前导下划线是正确的做法。毕竟,谁比编译器供应商更了解该语言?
编译器供应商使用前导下划线的原因是避免与代码发生冲突。一个好的编译器供应商之所以使用前导下划线,正是因为如果您不在任何名称中使用前导下划线,这样做可以防止其名称与您的名称发生冲突。切勿在类、全局变量、自由函数或预处理器符号的名称中使用前导下划线。前导下划线保留供编译器使用。
- 类没有命名C++代码中的类型错误
- 不完整类型错误(E0409、E0070、E0515)
- 使用具有结构不完整类型错误的模板
- 不命名构造函数和析构函数上的类型错误
- 返回派生类型时出现协变类型错误
- 为什么此构造函数没有给出不完整的类型错误?
- 定义模板化结构的特征时出现不完整的类型错误
- 使用重载构造函数时出现不完整的类型错误
- 为什么我得到表达式必须有类类型错误?
- 输出 [left]=input[i] 行中的 c++ 代码中存在无效的类型错误
- 枚举成员不是类型错误
- 如何修复"ctypes"。参数错误:参数 2:<键入"异常.类型错误">:RaspberryPi 中的错误类型"错误
- 外部 "C" Visual Studio 2015 中的显式类型错误,DLL 测试代码
- 非默认析构函数会导致不完整的类型错误
- 为什么按引用传入会导致绑定引用类型错误
- Objective-C C++ 包装器 类型错误的不完整定义
- 输入类型错误
- 当构造函数的参数类型错误时引发异常
- 命名空间中的'bad_cast' 'std' 未命名类型错误
- C UNWORKOWN类型错误