0

为方便起见,我使用以下方法。即在一个更大的程序中访问同一个 myapp 实例的一种方便的方法。代码可以在我的机器上正确编译和运行,但想问是否有人发现这种方法有任何问题?

比如 this ptr 是在构造函数中赋值给 the_app 的?那样行吗?我担心的是对象仍在构建中。但是如果构造函数的最后一行那么好吗?还是因为它是一个指针所以没关系,因为只要在完全构造时使用就会指向完整对象?

#include <iostream>

using namespace std;

class myapp
{
public:
   myapp() : m_data(0)
   {
     the_app = this;
   }

   void DoIt() { cout << "doing it\n"; }

   static myapp* the_app;

private:
   int m_data;
};

myapp* myapp::the_app = 0;

int main(int argc, char* argv[])
{
myapp app;

    app.DoIt();  //doing it using member function

    myapp::the_app->DoIt();  //accessing using static ptr
return 0;
}
4

6 回答 6

1

如果您追求的是对类的单个实例的静态访问,那么您可能需要查看 C++ Singleton 设计模式

于 2012-04-04T09:01:34.783 回答
1

这按预期工作。但是有几个问题:

  • 当实例被删除时,析构函数应该将类变量设置回零。你没有写那个。
  • 当创建另一个实例时,类变量会发生变化,这可能会导致第一个实例丢失......
  • 这似乎不是一个好主意(只是我个人的印象)
于 2012-04-04T08:50:18.993 回答
0

不行:

{
   myapp app;
}
myapp::the_app->DoIt(); 

这将是非法的,myapp::the_app在这个阶段的悬空指针也是如此。

于 2012-04-04T08:47:05.550 回答
0

如果您打算初始化它,那么不,您必须明确定义您的静态成员变量并在那里初始化它们

如果要显式初始化数据成员,则必须在定义中提供初始化程序

每个类只有一个,并且在所有对象之间共享。静态数据成员通过静态函数成员访问。

如果您不是要初始化,那么您需要考虑到您的类的每个新实例都会覆盖该值,并且您始终会创建最后一个指针。当您的类被破坏时 - 该指针可能会变得无效。

于 2012-04-04T08:47:19.607 回答
0

我可以看到的问题:

  1. 如果您将 myapp 子类化,则在分配指针时子类将不会完全构造。
  2. 析构函数中没有清除静态指针,myapp因为您还没有编写一个。如果您的真实代码没有在main().
  3. myapp多线程:如果您使用多线程,那么您会遇到问题,因为分配可能会在其余的初始化之前重新排序。根据平台的不同,分配指针也可能不是原子的。
于 2012-04-04T08:47:38.123 回答
0

正如其他人指出的那样,问题是:

  • 可能会在某个时候创建​​一个新实例,意外替换您的 my_app 实例
  • 当实例被销毁时,一个悬空指针仍然存在
  • 当您从 my_app 派生时,会在完全构造对象之前分配指针。

您可以通过添加来缓解前两个问题

assert(the_app == NULL);

给你的构造函数和

the_app = NULL;

到你的析构函数。

想到的替代解决方案:

std::scoped_ptr<my_app> the_global_app;

...如果您使用单个全局对象,您不妨承认您正在使用全局变量。在您的main功能中:

int main(int argc, char* argv[])
{
    the_global_app.reset( new myapp() ); // or a derived class

    the_global_app->DoIt();  //accessing using static ptr
    return 0;
}

如果您不打算从 派生myapp,您甚至可能会想使用一个普通的全局变量:

myapp the_global_app;

int main(int argc, char* argv[])
{
    the_global_app.DoIt();  //accessing using static ptr
    return 0;
}

...但是您需要注意,在不同源文件中定义的其他全局对象可能尚未初始化(std::cout但保证可用)。

于 2012-04-04T09:11:47.710 回答