首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何最好地处理C++对象初始化:空构造函数或指针?

如何最好地处理C++对象初始化:空构造函数或指针?
EN

Stack Overflow用户
提问于 2015-06-03 21:54:57
回答 5查看 15.5K关注 0票数 8

,我想知道,对于必须具有相对较大范围/较长生存期的对象,进行对象初始化和存储的最佳方法是什么。假设我们有一个GameEngine类,它需要初始化并保存对Window的引用来进行呈现。在整个程序的生命周期中都需要引用,并且窗口至少需要知道它的尺寸。

在Java中,我会这样做:

代码语言:javascript
复制
// Declaration:
Window window;
// Initialization:
window = new Window(width, height);

我了解到,在initialization.中,第一个已经调用了窗口类的默认构造函数,因此是声明因此,拥有一个window = Window(width, height);将是赋值,从而丢弃已经存在的对象。

我能找到的第一个解决方案是使用指针

代码语言:javascript
复制
// GameEngine.hpp
class GameEngine {
    Window *window;
};

// Somewhere in GameEngine.cpp:
window = new Window(width, height);

但是,我不断地阅读,只要有可能,我就会倾向于普通的对象而不是指针,事实上,我很快就陷入了一片混乱,所以我正在寻找另一种方法。

另一种解决方案似乎是将对象设计成没有参数的构造函数,并在稍后的上设置该对象。

代码语言:javascript
复制
// GameEngine.hpp
class GameEngine {
    Window window;
};

// Somewhere in GameEngine.cpp
window.setWidth(width);
window.setHeight(height);

这是可行的,但有一个严重的缺点:对象(至少在这种情况下)可能处于不一致的状态,因为尝试在不设置宽度/高度的情况下显示窗口会导致错误或崩溃。它确实对某些对象有效,但对大多数对象则不起作用。

避免这种情况的一种方法是使用默认值。例如,窗口类的构造函数可能类似于以下

代码语言:javascript
复制
Window::Window(int width = 800, int height = 600) {}

,甚至像那样

代码语言:javascript
复制
Window::Window() : width(DEFAULT_WIDTH), height(DEFAULT_HEIGHT) {}

但在许多情况下,默认值将难以确定。还有,他们应该从哪里来?窗口类应该定义DEFAULT_WIDTHDEFAULT_HEIGHT吗?还是应该这样做?

代码语言:javascript
复制
// GameEngine.hpp
class GameEngine {
    static const int DEFAULT_WIDTH = 800;
    static const int DEFAULT_HEIGHT = 600;
    Window window(800,600);
};

但这似乎很糟糕,因为我已经读过,您不应该在标头中进行任何初始化,只进行声明,因此此时不应该实际知道DEFAULT_WIDTHDEFAULT_HEIGHT的值(并且只在.cpp中初始化,对吗?)

我错过了一个选项吗?还是C++中很常见的假设:程序员应该知道自己在做什么,并在使用对象之前处理好保持一致的状态?什么时候使用哪种方法?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-06-03 22:21:33

如果您只想构造一次,并且可以在类的初始化中完成,那么就不需要指针了。您可以声明它为成员,并在构造函数中初始化它,如下所示:

HPP

代码语言:javascript
复制
class Game
{
    private:
        Window window_;

    public:
        Game(int, int);
}

CPP

代码语言:javascript
复制
Game::Game(int width, int height) : window_(width, height)
{
}

这将在构造游戏对象时构造窗口对象,并且它将持续到游戏对象被销毁为止。如果您希望以后能够构造它或在任何时候重构它,那么可以使用如下所示的std::unique_ptr:

HPP

代码语言:javascript
复制
class Game
{
    private:
       std::unique_ptr<Window> window_;

    public:
        Game(int, int);
        void SomeMethod(int, int);

}

CPP

代码语言:javascript
复制
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的文档

票数 5
EN

Stack Overflow用户

发布于 2015-06-03 22:03:24

你显然误解了C++。你永远不会在头上有这样的Window window;。它定义了一个窗口对象,每次包含标题时都是如此!

您可能有class GameEngine { Window window; .... },但这实际上根本没有设置一个窗口。每个GameEngine构造函数都有一个初始化程序列表,并在那里初始化window。很有意义:游戏引擎创建了它需要的窗口。

票数 2
EN

Stack Overflow用户

发布于 2015-06-03 22:03:38

如果您谈论的是类成员,那么声明并不是调用构造函数的同一点。初始化这些成员正是初始化程序列表(您似乎知道)的目的!

代码语言:javascript
复制
class Window {
   int x;
   int y;
 public:
   Window(int x, int y);
 };

代码语言:javascript
复制
class Game {
 Window window;
public:
 Game();
};

然后,您可以从游戏构造函数调用窗口类的构造函数,如下所示:

代码语言:javascript
复制
Game::Game() : window(DEFAULT_HEIGHT, DEFAULT_WIDTH) {}

如果您说的是全局对象:如果您确实需要一个全局对象(尽管您可能不希望这样),那么您可以(而且应该!)在标头中声明具有外部链接的对象(这只会使名称可用,但不会调用任何构造函数),并在实现中执行定义:

声明:

代码语言:javascript
复制
extern Window window;

执行情况:

代码语言:javascript
复制
Window window(DEFAULT_WIDTH, DEFAULT_HEIGHT);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30631467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档