,我想知道,对于必须具有相对较大范围/较长生存期的对象,进行对象初始化和存储的最佳方法是什么。假设我们有一个GameEngine类,它需要初始化并保存对Window的引用来进行呈现。在整个程序的生命周期中都需要引用,并且窗口至少需要知道它的尺寸。
在Java中,我会这样做:
// Declaration:
Window window;
// Initialization:
window = new Window(width, height);我了解到,在initialization.中,第一个已经调用了窗口类的默认构造函数,因此是声明和因此,拥有一个window = Window(width, height);将是赋值,从而丢弃已经存在的对象。
我能找到的第一个解决方案是使用指针
// GameEngine.hpp
class GameEngine {
Window *window;
};
// Somewhere in GameEngine.cpp:
window = new Window(width, height);但是,我不断地阅读,只要有可能,我就会倾向于普通的对象而不是指针,事实上,我很快就陷入了一片混乱,所以我正在寻找另一种方法。
另一种解决方案似乎是将对象设计成没有参数的构造函数,并在稍后的上设置该对象。
// GameEngine.hpp
class GameEngine {
Window window;
};
// Somewhere in GameEngine.cpp
window.setWidth(width);
window.setHeight(height);这是可行的,但有一个严重的缺点:对象(至少在这种情况下)可能处于不一致的状态,因为尝试在不设置宽度/高度的情况下显示窗口会导致错误或崩溃。它确实对某些对象有效,但对大多数对象则不起作用。
避免这种情况的一种方法是使用默认值。例如,窗口类的构造函数可能类似于以下
Window::Window(int width = 800, int height = 600) {},甚至像那样
Window::Window() : width(DEFAULT_WIDTH), height(DEFAULT_HEIGHT) {}但在许多情况下,默认值将难以确定。还有,他们应该从哪里来?窗口类应该定义DEFAULT_WIDTH和DEFAULT_HEIGHT吗?还是应该这样做?
// GameEngine.hpp
class GameEngine {
static const int DEFAULT_WIDTH = 800;
static const int DEFAULT_HEIGHT = 600;
Window window(800,600);
};但这似乎很糟糕,因为我已经读过,您不应该在标头中进行任何初始化,只进行声明,因此此时不应该实际知道DEFAULT_WIDTH和DEFAULT_HEIGHT的值(并且只在.cpp中初始化,对吗?)
我错过了一个选项吗?还是C++中很常见的假设:程序员应该知道自己在做什么,并在使用对象之前处理好保持一致的状态?什么时候使用哪种方法?
发布于 2015-06-03 22:21:33
如果您只想构造一次,并且可以在类的初始化中完成,那么就不需要指针了。您可以声明它为成员,并在构造函数中初始化它,如下所示:
HPP
class Game
{
private:
Window window_;
public:
Game(int, int);
}CPP
Game::Game(int width, int height) : window_(width, height)
{
}这将在构造游戏对象时构造窗口对象,并且它将持续到游戏对象被销毁为止。如果您希望以后能够构造它或在任何时候重构它,那么可以使用如下所示的std::unique_ptr:
HPP
class Game
{
private:
std::unique_ptr<Window> window_;
public:
Game(int, int);
void SomeMethod(int, int);
}CPP
Game::Game(int width, int height)
{
window_ = std::make_unique<Window>(width, height);
}
Game::SomeMethod(int width, int height)
{
window_ = std::make_unique<Window>(width, height);
}这将在游戏对象被销毁时自动删除窗口,并在每次调用std::make_unique构建新窗口时自动删除该窗口。下面是一些关于unique_ptr:ptr的文档
发布于 2015-06-03 22:03:24
你显然误解了C++。你永远不会在头上有这样的Window window;。它定义了一个窗口对象,每次包含标题时都是如此!
您可能有class GameEngine { Window window; .... },但这实际上根本没有设置一个窗口。每个GameEngine构造函数都有一个初始化程序列表,并在那里初始化window。很有意义:游戏引擎创建了它需要的窗口。
发布于 2015-06-03 22:03:38
如果您谈论的是类成员,那么声明并不是调用构造函数的同一点。初始化这些成员正是初始化程序列表(您似乎知道)的目的!
class Window {
int x;
int y;
public:
Window(int x, int y);
};和
class Game {
Window window;
public:
Game();
};然后,您可以从游戏构造函数调用窗口类的构造函数,如下所示:
Game::Game() : window(DEFAULT_HEIGHT, DEFAULT_WIDTH) {}如果您说的是全局对象:如果您确实需要一个全局对象(尽管您可能不希望这样),那么您可以(而且应该!)在标头中声明具有外部链接的对象(这只会使名称可用,但不会调用任何构造函数),并在实现中执行定义:
声明:
extern Window window;执行情况:
Window window(DEFAULT_WIDTH, DEFAULT_HEIGHT);https://stackoverflow.com/questions/30631467
复制相似问题