我正在设计一个界面来抽象管理Direct3D,Direct2D,DXGI和相关的Win32API调用的任务。
将所有内容保留在命名空间或重构中以使用类吗?
WindowsApp.h
#pragma once
#include <Windows.h>
namespace WindowsApp
{
bool Initialize(HINSTANCE instanceHandle);
}
WindowsApp.cpp
#include "WindowsApp.h"
namespace WindowsApp
{
namespace
{
HWND ghMainWnd = 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
default:
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
}
}
bool Initialize(HINSTANCE instanceHandle)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instanceHandle;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"BasicWndClass";
if (!RegisterClass(&wc))
{
MessageBox(0, L"RegisterClass FAILED", 0, 0);
return false;
}
ghMainWnd = CreateWindow(
L"BasicWndClass",
L"Win32Basic",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
instanceHandle,
0);
if (ghMainWnd == 0)
{
MessageBox(0, L"CreateWindow FAILED", 0, 0);
}
ShowWindow(ghMainWnd, 1);
UpdateWindow(ghMainWnd);
return true;
}
}
Main.cpp的
#include "WindowsApp.h"
int Run()
{
MSG msg = { 0 };
BOOL bRet = 1;
while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0)
{
if (bRet == -1)
{
MessageBox(0, L"GetMessage FAILED", L"Error", MB_OK);
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// Deinitialize Here
return (int)msg.wParam;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd)
{
if (!WindowsApp::Initialize(hInstance)) { return 0; }
return Run();
}
使用命名空间允许我在嵌套的未命名命名空间中隐藏实现细节。 一堂课不会让我隐藏东西,但我可以让它们在私人区域内无法进入,我认为这已经足够了。
使用类会冒用户尝试实例化多个对象的风险,这会导致应用程序因初始化DirectX两次崩溃而崩溃。
命名空间避免了这个问题,但是它们会出现性能下降因素,我必须在每个函数调用期间检查Initialized
变量。我真的不喜欢这个。
最后,使用类需要用户在需要底层方法的任何地方传递实例化对象。这真的很令人失望,因为只要我在一个文件中有命名空间头文件的#include
,命名空间方法就会让我访问。我真的很喜欢这个。
命名空间方法似乎是最好的方法,但是在嵌套的未命名命名空间内处理变量的方式中,某些东西并不适合我。 这是一个好的做法吗?我的直觉告诉我没有!没有!没有!
所以我想我的问题是:这是名称空间的合适用例吗?
澄清: 我在WindowsApp.cpp中定义了未命名的命名空间以及函数定义 - 所有函数的前向声明都在WindowsApp.h中 - 通过使用调用这些函数来操作未命名的命名空间内的变量。这是命名空间的错误使用还是应该以不同的方式完成?只需在任何其他.cpp中包含头文件,您就可以访问这些函数,进而可以访问基础数据。这非常有吸引力。我的直觉告诉我,这种结构会产生某种性能损失。
答案 0 :(得分:2)
[编辑:删除有关未命名的命名空间的内容开始对TU而言是唯一的,现在问题中的代码已经澄清。]
在C ++中,我们倾向于认为class
是一些保持不变量的数据的包装器(而不是struct
,它往往用于一堆数据而没有不变)。构造函数建立了不变量,析构函数将其删除,成员函数小心地维护它。在这里,如果我理解正确,那么在使用任何其他API函数之前,Initialized()
必须调用您的不变量。
还有另一种选择,即使用所谓的&#34;魔法静电&#34;,也称为&#34; Meyers singletons&#34;。做类似以下的事情:
// In WindowsApp.cpp
namespace {
class WindowsAppImpl {
public:
WindowsAppImpl()
{
// Do initialization stuff here
}
~WindowsAppImpl()
{
// Do teardown stuff if necessary
}
// Example function
int getMagicNumber()
{
return 3;
}
};
WindowsAppImpl& GetInstance() {
static WindowsAppImpl instance{};
return instance;
}
} // end private namespace
// Public function declared in WindowApp.h
int GetMagicNumber() {
// Get the singleton instance
WindowsAppImpl& instance = GetInstance();
// Call member function
return instance.getMagicNumber();
}
此方法添加一个函数,该函数返回对单例WindowsAppImpl
实例的引用。编译器保证在第一次调用GetInstance()
时,该实例只构造一次。 (它还将在WindowsAppImpl
完成后运行main()
的析构函数,这在这种情况下可能并不重要,但在某些情况下可能很有用。)这种方法的优点是内部{{1你可以确定已经运行了初始化例程,而不需要用户传递他们自己的某种GetMagicNumber()
实例。