崩溃,在施工前使用它

时间:2013-01-31 15:45:56

标签: c++

我有一个类,其对象将由另一个类使用,如下所示

class A
{
public:
    void F() {...}
};

class B
{
public:
    void G() { m_a->F(); ...} // use A's function

private:
    A* m_a;
};

因此,在指针m_a的赋值之前调用B :: G()是错误的。这是可接受的设计吗?或者有一种更好的方法。

问题来自开发GUI应用程序。我在主窗口下面有一个窗口,显示当前操作的一些基本信息,例如发生了什么,需要多长时间等等。我把这个窗口作为一个单独的窗口,以方便访问可能分散在任何地方的操作,并在关闭GUI应用程序时发现代码崩溃。崩溃是由于在删除GUI应用程序(例如Qt中的qApp)后删除了窗口。然后我只是将窗口的引用指针放在单例中。构建窗口时,我设置了引用指针。窗口的删除由主窗口控制。因此解决了上述碰撞问题。但是如果其他开发人员在构造窗口之前使用单例,代码也会崩溃。有什么好方法可以解决吗?或者我们可以接受它,因为在构建之前使用它是开发人员的错误?非常感谢!

3 个答案:

答案 0 :(得分:3)

如果G()未初始化,则调用函数m_a可能会导致未定义的行为,因此您需要确保从未出现过这种情况。你必须改变你的代码,使它看起来像这样:

class B
{

public:

    B() : m_a(nullptr) { } // m_a always initialized!

    bool G() 
    { 
        if (m_a == nullptr) return false; // No Undefined Behavior!
        m_a->F(); // This call is safe now
        ...
        return true;
    }

private:

    A* m_a;

};

顺便说一句,一般来说,你应该使用智能指针(选择实现适当所有权语义的类型)而不是原始指针,除非你有充分的理由这样做。这甚至可以避免手动初始化(假设共享所有权):

#include <memory>

class B
{

public:

    bool G() 
    { 
        if (m_a == nullptr) return false; // No Undefined Behavior!
        m_a->F(); // This call is safe now
        ...
        return true;
    }

private:

    std::shared_ptr<A> m_a; // Automatically initalized to nullptr

};

答案 1 :(得分:2)

您必须使用 member initializer list 初始化 m_a,而不是分配。 它确保您在调用其他函数之前不必费心去分配m_a

答案 2 :(得分:1)

根据您对课程的预期用法,这可能是一种可接受的做法,但如果您这样做,最好更改B::G()以首先检查指针:

void G() { if (m_a) m_a->F(); ...}

并确保在所有构造函数中初始化m_a,如果您当前没有真正的A指向,则至少为空指针。