我有一个类,其对象将由另一个类使用,如下所示
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)后删除了窗口。然后我只是将窗口的引用指针放在单例中。构建窗口时,我设置了引用指针。窗口的删除由主窗口控制。因此解决了上述碰撞问题。但是如果其他开发人员在构造窗口之前使用单例,代码也会崩溃。有什么好方法可以解决吗?或者我们可以接受它,因为在构建之前使用它是开发人员的错误?非常感谢!
答案 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
指向,则至少为空指针。