在这种情况下我应该使用引用成员吗?

时间:2015-03-05 18:28:19

标签: c++ class reference smart-pointers

我是计算机科学专业的学生,​​我自己学习C ++并尝试编写一个干净的C ++程序。

这是我的问题: 我正在编写一个将成为该程序主要类的App类,并且我希望我的很多类可以访问将在main函数中创建的App对象。

基本上主要功能看起来像

int main(int argc, char *argv[])
{
   App myApp;

   return myApp.run();
}

App类会有很多来自类的对象需要引用(或者在这种情况下还有其他更好的东西吗?)到应用程序。 这是一个需要它的类的例子

class AppStateHandler{
private:
    /// < Reference to the App
    App& m_app;
public:
    AppStateHandler(); // How can I initialize m_app with that ??

    /// @param app The app the AppStateHandler will work with
    AppStateHandler(App &app);
};

以下是我的问题,在这种情况下使用引用作为类成员是不是很糟糕?我应该使用某种智能指针吗? 在使用引用的情况下,我无法创建默认构造函数,因为 m_app必须在构造函数初始化列表中初始化,因此,不要错过#39 ; t有默认构造函数吗?

如果您对如何改进我感兴趣的代码有任何建议。

非常感谢!

编辑:我实际上想让AppStateHandler成为App的成员。主函数中声明的唯一对象是App。

4 个答案:

答案 0 :(得分:2)

在这种情况下使用引用意味着应用程序不能为NULL。但是只有在保证对象的生命周期始终在父对象的生命周期内时才使用引用。如果没有,请使用智能指针。

答案 1 :(得分:1)

你可以使用引用,你甚至可以使用智能指针(虽然这样做没什么意义),但是你的问题为另一个解决方案而尖叫:a singleton

要使用单例模式,您可以向App类添加一个静态方法,该类只负责返回对唯一App对象的引用。 App的构造函数应该是私有的,因此其他代码不能生成第二个App对象。实现看起来像这样:

class App {
    private:
        App();
        App(App const&) = delete;

    public:
        static App& getApp() {
            static App theApp;
            return theApp;
        }
}

通过简单地调用App,所有其他对象都可以引用App::getApp()对象。

答案 2 :(得分:1)

首先,正如评论中所提到的,你应该考虑是否要将app对象的引用传递给每个成员对象(我在这里使用术语引用用于任何事情,引用另一个对象,无论是原始/智能指针还是实际参考)。结果是程序中的任何函数调用都可能改变程序中的任何其他状态。如果你的对象需要一个窗口的引用来绘制一些东西,那么只需给它们一个窗口的引用而不是别的。

接下来,你不应该在这里使用智能指针,原因有两个:大多数智能指针(例如std::unique_ptrstd::shared_ptr)代表拥有关系。然而,对父对象的引用恰恰相反。其次,据我了解程序的设计,主应用程序对象的生命周期 - 按设计 - 无论如何都会超过程序中任何其他对象的生命周期,因此您不必担心终生问题。 / p>

然后有关于指针与引用的问题:通常,由于应用程序的生命周期将超过任何其他对象的生命周期,因此使用引用没有任何害处(除非您需要能够默认构建您的宾语)。 就“好”的软件设计而言,你应该问自己每个班级,无论该班级是否有意义,而不参考主应用程序。如果没有,请使用参考。如果是,请使用指针,在使用之前始终与nullptr进行核对。

最后:如果您已经确定,大多数对象确实需要该引用,并且您的程序逻辑是这样的,那么只能有一个App,那么您可以考虑将其实现为单例。虽然我不是他们的忠实粉丝,但他们并没有比在程序中传递对每个单个对象的引用更糟糕。另一方面,当某些对象仅保留“传递它”但不自行使用它的引用时,它们有时可以简单地使用您的代码。

答案 3 :(得分:0)

不使用默认构造函数也不错。

我不认为这是一个&#34;参考VS指针&#34;题。它看起来更像是对象的生命周期和所有权管理。

有多种方法可以确保推荐人在裁判的有效期内。

在您的情况下,您正在main()的堆栈中构建它们,这是正确的。或者,您可以AppStateHandler成为App的成员,具体取决于您的设计目的。

需要注意的是,随着AppStateHandler的增长,它会有很多成员类/对象,方法,每个只需要少量的工作,并且真的不需要访问整个App。将整个App传递给他们中的每一个都会很快使你的代码变得讨厌。

所以,再次,根据您的设计目的,无论您选择哪个,指针或参考,都不要过多。

P.S。我相信使用shared_ptr / unique_ptr管理范围内的生命周期/所有权表明设计不佳。 99%的时间你可以通过RAII等其他设计技术避免所有权转移的必要性。当绝对必要时,智能指针适用于另一个1%。