gpt4 book ai didi

c++ - 可以在没有主体的情况下调用声明的函数

转载 作者:行者123 更新时间:2023-11-30 03:11:21 26 4
gpt4 key购买 nike

你能在你的代码中调用一个没有主体但在头文件中声明的函数吗?请阅读下面我的情况。

我正在学习 C++,所以如果我的术语不合时宜,你就知道为什么了。无论如何,我正在阅读这本名为“高级 2D 游戏开发”的书,所以如果有人读过这本书,那么也许他们可以帮助我。在c++中他在Advanced2D.h中设置了4个extern函数

extern bool game_preload();
extern bool game_init(HWND);
extern void game_update();
extern void game_end();

后来,他在类里面多次拜访他们,但从未给他们一个 body 。他最终尝试将所有代码编译成 lib 文件,以便其他项目可以包含它并实际使用这 4 种方法。

他要我转到解决方案属性/常规/输出目录并将其添加到发布和调试配置中

$(ProjectDir)..\lib\Advance2D.lib // It didn't work. Still added the libs at default location

只有在像这样的另一个项目中使用上面的那些方法。这是声明性方法获得主体的时候。

#include <iostream>
#include "..\Engine\Advanced2D.h"
bool game_preload()
{
//display engine version in a message box
g_engine->message(g_engine->getVersionText(), "TEST ENGINE");
//return fail to terminate the engine
return false;
}

bool game_init(HWND hwnd) { return 0;}
void game_update() {}
void game_end() {}

现在唯一的问题是我收到链接器错误

1>winmain.obj : error LNK2019: unresolved external symbol "bool __cdecl game_preload(void)" (?game_preload@@YA_NXZ) referenced in function _WinMain@16
1>c:\Engine\msvc8\Advance2D\Advance2D\..\lib\Advance2D.lib\Advance2D.exe : fatal error LNK1120: 1 unresolved externals

如果我不注释掉第一个项目中使用的那些方法,那么该项目永远不会被编译?

那家伙坚持认为我在编译时不应收到任何链接器错误。我引用以下内容

Assuming you have typed the code into the specified files without any mistakes, you should be able to compile the engine project. There should be no dependencies for the engine because the compiler assumes that you will provide the needed libs at link time (when you create an executable using the engine’s lib). This is a rather complex issue that we’ll examine again over the next several chapters as we enhance the engine with new modules and functionality. You should not see any linker errors, only compiler errors if you have made a mistake while typing in the code.

下面是advanced2D header

// Advanced2D Engine
// Main header file
#ifndef _ADVANCED2D_H
#define _ADVANCED2D_H 1
#include <iostream>
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dxerr.h>
#include "Timer.h"
#define VERSION_MAJOR 1
#define VERSION_MINOR 0
#define REVISION 0

#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib, "winmm.lib")

//external variables and functions
extern bool gameover;
extern bool game_preload();
extern bool game_init(HWND);
extern void game_update();
extern void game_end();

namespace Advanced2D
{
class Engine {
private:
int p_versionMajor, p_versionMinor, p_revision;
HWND p_windowHandle;
LPDIRECT3D9 p_d3d;
LPDIRECT3DDEVICE9 p_device;
LPDIRECT3DSURFACE9 p_backbuffer;
LPD3DXSPRITE p_sprite_handler;
std::string p_apptitle;
bool p_fullscreen;
int p_screenwidth;
int p_screenheight;
int p_colordepth;
bool p_pauseMode;
D3DCOLOR p_ambientColor;
bool p_maximizeProcessor;
Timer p_coreTimer;
long p_frameCount_core;
long p_frameRate_core;
Timer p_realTimer;
long p_frameCount_real;
long p_frameRate_real;
public:
Engine();
virtual ~Engine();
int Init(int width, int height, int colordepth, bool fullscreen);
void Close();
void Update();
void message(std::string message, std::string title = "ADVANCED 2D");
void fatalerror(std::string message, std::string title = "FATAL ERROR");
void Shutdown();
void ClearScene(D3DCOLOR color);
void SetDefaultMaterial();
void SetAmbient(D3DCOLOR colorvalue);
int RenderStart();
int RenderStop();
int Release();
//accessor/mutator functions expose the private variables
bool isPaused() { return this->p_pauseMode; }
void setPaused(bool value) { this->p_pauseMode = value; }
LPDIRECT3DDEVICE9 getDevice() { return this->p_device; }
LPDIRECT3DSURFACE9 getBackBuffer() { return this->p_backbuffer; }
LPD3DXSPRITE getSpriteHandler() { return this->p_sprite_handler; }
void setWindowHandle(HWND hwnd) { this->p_windowHandle = hwnd; }
HWND getWindowHandle() { return this->p_windowHandle; }
std::string getAppTitle() { return this->p_apptitle; }
void setAppTitle(std::string value) { this->p_apptitle = value; }
int getVersionMajor() { return this->p_versionMajor; }
int getVersionMinor() { return this->p_versionMinor; }
int getRevision() { return this->p_revision; }
std::string getVersionText();
long getFrameRate_core() { return this->p_frameRate_core; };
long getFrameRate_real() { return this->p_frameRate_real; };
int getScreenWidth() { return this->p_screenwidth; }
void setScreenWidth(int value) { this->p_screenwidth = value; }
int getScreenHeight() { return this->p_screenheight; }
void setScreenHeight(int value) { this->p_screenheight = value; }
int getColorDepth() { return this->p_colordepth; }
void setColorDepth(int value) { this->p_colordepth = value; }
bool getFullscreen() { return this->p_fullscreen; }
void setFullscreen(bool value) { this->p_fullscreen = value; }
bool getMaximizeProcessor() { return this->p_maximizeProcessor; }
void setMaximizeProcessor(bool value) { this->p_maximizeProcessor = value;}
}; //class
}; //namespace
//define the global engine object (visible everywhere!)
extern Advanced2D::Engine *g_engine;
#endif

Advanced2d 类

// Advanced2D Engine
// Main source code file
//includes
#include "Advanced2D.h"
#include <cstdlib>
#include <ctime>
#include <string>
#include <sstream>
#include <list>
#include "winmain.h"

namespace Advanced2D
{
Engine::Engine()
{
srand((unsigned int)time(NULL));
p_maximizeProcessor = false;
p_frameCount_core = 0;
p_frameRate_core = 0;
p_frameCount_real = 0;
p_frameRate_real = 0;
p_ambientColor = D3DCOLOR_RGBA(255,255,255, 0);
p_windowHandle = 0;
p_pauseMode = false;
p_versionMajor = VERSION_MAJOR;
p_versionMinor = VERSION_MINOR;
p_revision = REVISION;
//set default values
this->setAppTitle("Advanced2D");
this->setScreenWidth(640);
this->setScreenHeight(480);
this->setColorDepth(32);
this->setFullscreen(false);
//window handle must be set later on for DirectX!
this->setWindowHandle(0);
}

Engine::~Engine()
{
if (this->p_device) this->p_device->Release();
if (this->p_d3d) this->p_d3d->Release();
}

std::string Engine::getVersionText()
{
std::ostringstream s;
s << "Advanced2D Engine v" << p_versionMajor << "." << p_versionMinor
<< "." << p_revision;
return s.str();
}

void Engine::message(std::string message, std::string title)
{
MessageBox(0, message.c_str(), title.c_str(), 0);
}

void Engine::fatalerror(std::string message, std::string title)
{
this->message(message,title);
Shutdown();
}

int Engine::Init(int width, int height, int colordepth, bool fullscreen)
{
//initialize Direct3D

this->p_d3d = Direct3DCreate9(D3D_SDK_VERSION);

if (this->p_d3d == NULL) {
return 0;
}

//get system desktop color depth
D3DDISPLAYMODE dm;
this->p_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm);

//set configuration options for Direct3D
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = (!fullscreen);
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.BackBufferFormat = dm.Format;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.hDeviceWindow = p_windowHandle;

//create Direct3D device
this->p_d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
this->p_windowHandle,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp,
&this->p_device);
if (this->p_device == NULL) return 0;

//clear the backbuffer to black
this->ClearScene(D3DCOLOR_XRGB(0,0,0));

//create pointer to the back buffer
this->p_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &this->p_backbuffer);

//use ambient lighting and z-buffering
this->p_device->SetRenderState(D3DRS_ZENABLE, TRUE);
this->p_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
this->SetAmbient(this->p_ambientColor);

//initialize 2D renderer
HRESULT result = D3DXCreateSprite(this->p_device, &this->p_sprite_handler);
if (result != D3D_OK) return 0;
//call game initialization extern function
//if (!game_init(this->getWindowHandle())) return 0;
//set a default material
SetDefaultMaterial();
return 1;
}


void Engine::SetDefaultMaterial()
{
D3DMATERIAL9 mat;
memset(&mat, 0, sizeof(mat));
mat.Diffuse.r = 1.0f;
mat.Diffuse.g = 1.0f;
mat.Diffuse.b = 1.0f;
mat.Diffuse.a = 1.0f;
p_device->SetMaterial(&mat);
}

void Engine::ClearScene(D3DCOLOR color)
{
this->p_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
color, 1.0f, 0);
}

void Engine::SetAmbient(D3DCOLOR colorvalue)
{
this->p_ambientColor = colorvalue;
this->p_device->SetRenderState(D3DRS_AMBIENT, this->p_ambientColor);
}
int Engine::RenderStart()
{
if (!this->p_device) return 0;
if (this->p_device->BeginScene() != D3D_OK) return 0;
return 1;
}
int Engine::RenderStop()
{
if (!this->p_device) return 0;
if (this->p_device->EndScene() != D3D_OK) return 0;
if (p_device->Present(NULL, NULL, NULL, NULL) != D3D_OK) return 0;
return 1;
}

void Engine::Shutdown()
{
gameover = true;
}

void Engine::Update()
{
static Timer timedUpdate;
//calculate core framerate
p_frameCount_core++;
if (p_coreTimer.stopwatch(999)) {
p_frameRate_core = p_frameCount_core;
p_frameCount_core = 0;
}
//fast update with no timing
game_update();

//update with 60fps timing
if (!timedUpdate.stopwatch(14)) {
if (!this->getMaximizeProcessor())
{
Sleep(1);
}
}
else {
//calculate real framerate
p_frameCount_real++;

if (p_realTimer.stopwatch(999)) {
p_frameRate_real = p_frameCount_real;
p_frameCount_real = 0;
}
//begin rendering
this->RenderStart();
//done rendering
this->RenderStop();
}
}
void Engine::Close()
{
game_end();
}
} //namespace

这是 WinMain

#include <sstream>
#include "winmain.h"
#include "Advanced2D.h"
//macro to read the key states
#define KEY_DOWN(vk) ((GetAsyncKeyState(vk) & 0x8000)?1:0)
HINSTANCE g_hInstance;
HWND g_hWnd;
int g_nCmdShow;
//declare global engine object
Advanced2D::Engine *g_engine;
bool gameover;


//window event callback function
LRESULT WINAPI WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_QUIT:
case WM_CLOSE:
case WM_DESTROY:
gameover = true;
break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int
nCmdShow)
{
MSG msg;
srand((unsigned int)time(NULL));
g_hInstance = hInstance;
g_nCmdShow = nCmdShow;
DWORD dwStyle, dwExStyle;
RECT windowRect;
/**
* Create engine object first!
**/
g_engine = new Advanced2D::Engine();
//let main program have a crack at things before window is created
if (!game_preload()) {
MessageBox(g_hWnd, "Error in game preload!", "Error", MB_OK);
return 0;
}
//get window caption string from engine
char title[255];
sprintf_s(title, "%s", g_engine->getAppTitle().c_str());
//set window dimensions
windowRect.left = (long)0;
windowRect.right = (long)g_engine->getScreenWidth();
windowRect.top = (long)0;
windowRect.bottom = (long)g_engine->getScreenHeight();
//create the window class structure
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
//fill the struct with info
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = title;
wc.hIconSm = NULL;
//set up the window with the class info
RegisterClassEx(&wc);
//set up the screen in windowed or fullscreen mode?
if (g_engine->getFullscreen())
{
DEVMODE dm;
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(dm);
dm.dmPelsWidth = g_engine->getScreenWidth();
dm.dmPelsHeight = g_engine->getScreenHeight();
dm.dmBitsPerPel = g_engine->getColorDepth();
dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
g_engine->setFullscreen(false);
}
dwStyle = WS_POPUP;
dwExStyle = WS_EX_APPWINDOW;
ShowCursor(FALSE);
}
else {
dwStyle = WS_OVERLAPPEDWINDOW;
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
}
//adjust window to true requested size
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
//create the program window
g_hWnd = CreateWindowEx( 0,
title, //window class
title, //title bar
dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, //x,y coordinate
windowRect.right - windowRect.left, //width of the window
windowRect.bottom - windowRect.top, //height of the window
0, //parent window
0, //menu
g_hInstance, //application instance
0); //window parameters
//was there an error creating the window?
if (!g_hWnd) {
MessageBox(g_hWnd, "Error creating program window!", "Error", MB_OK);
return 0;
}
//display the window
ShowWindow(g_hWnd, g_nCmdShow);
UpdateWindow(g_hWnd);
//initialize the engine
g_engine->setWindowHandle(g_hWnd);
if (!g_engine->Init(g_engine->getScreenWidth(), g_engine->getScreenHeight(),
g_engine->getColorDepth(), g_engine->getFullscreen())) {
MessageBox(g_hWnd, "Error initializing the engine", "Error", MB_OK);
return 0;
}
// main message loop
gameover = false;
while (!gameover)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
g_engine->Update();
}

if (g_engine->getFullscreen()) {
ShowCursor(TRUE);
}
g_engine->Close();
delete g_engine;
return 1;
}

最佳答案

extern 关键字指定该函数将在您所在的编译对象外部的编译对象中实现 - 通常通过 lib 或其他对象。如果您要在一个 cpp 文件中(在任何函数体之外)在全局范围内声明一个变量,您只能在另一个 cpp 文件中使用外部 {variable declaration} 引用它 - 这样编译器就知道不要期望函数/变量被定义但知道它存在。

这里发生的事情的声音是你链接到的对象实际上并没有被链接——它应该是。上面的答案告诉你如何——我不够快!从您的问题看来,您似乎拥有第二个项目的源代码并且可能需要自己构建它 - 当然我不知道,但是如果 .lib 不存在那么您将需要。

关于c++ - 可以在没有主体的情况下调用声明的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2323901/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com