在这种情况下,我应该使用参考成员吗

Should I use references members in this case?

本文关键字:参考 成员 这种情况下 我应该      更新时间:2023-10-16

我是一名计算机科学专业的学生,我正在自学C++,并试图编写一个干净的C++程序。

这是我的问题:我正在编写一个应用程序类,它将成为程序的主类,我希望我的很多类都可以访问将在主函数中创建的应用程序对象。

基本上,主要功能将看起来像

int main(int argc, char *argv[])
{
   App myApp;
   return myApp.run();
}

应用程序类将有许多来自类的对象,这些对象需要对应用程序的引用(或者在这种情况下还有更好的东西吗?)。下面是一个需要它的类的例子

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必须在构造函数初始化列表中初始化所以,没有默认构造函数不好吗?

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

非常感谢!

EDIT:我实际上想作为应用程序的一员创建一个AppStateHandler。在主函数中声明的唯一对象是应用程序

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

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

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

然后是指针与引用的问题:一般来说,由于应用程序的生存期将超过任何其他对象的生存期,使用引用没有害处(除非你需要默认构造对象的能力)。就"好"的软件设计而言,你应该为每一个类问问自己,这个类是否有意义,而不需要参考主应用程序。如果没有,请使用引用。如果是,请使用一个指针,在使用它之前,您总是对照nullptr进行检查。

最后:如果您已经确定,您的大多数对象确实需要该引用,并且您的程序逻辑是这样的,只能有一个应用程序,那么您可以考虑将其实现为单例。虽然我不是它们的铁杆粉丝,但它们并不比在程序中传递对每个对象的引用差多少。另一方面,当一些对象只持有"传递它"的引用,而不单独使用它时,它们有时可以简化代码。

不使用默认构造函数一点也不坏。

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

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

在您的案例中,您正在main()的堆栈中构建这两个堆栈,这是正确的。或者,您可以将AppStateHandler作为App的成员,这取决于您设计的目的。

需要注意的是,随着AppStateHandler的增长,它将有很多成员类/对象、方法,每一个只做少量的工作,实际上不需要访问整个App。将整个App传递给它们中的每一个很快就会使代码变得糟糕。

所以,同样,根据你的设计目的,无论你选择哪一个,指针还是引用,都不要传递太多信息。

第页。S.我认为使用shared_ptr/unique_ptr来跨范围管理生存期/所有权表明设计很糟糕。99%的情况下,您可以通过RAII等其他设计技术避免所有权转移的必要性。当绝对必要时,智能指针用于其他1%。

您可以使用引用,甚至可以使用智能指针(尽管这样做没有什么意义),但您的问题需要另一种解决方案:singleton。

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

class App {
    private:
        App();
        App(App const&) = delete;
    public:
        static App& getApp() {
            static App theApp;
            return theApp;
        }
}

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