【问题标题】:classes before main and design issues in C++C++ 中主要和设计问题之前的类
【发布时间】:2013-02-12 06:31:23
【问题描述】:

第 1 部分: 我有一个非常奇怪的情况,在这种情况下,我必须在 main() 之前或在它进入 main() 时立即调用几个类的构造函数。还有另一个子系统需要该数据尽快启动这个子系统的 main() 和更多的东西,这使得这个概念看起来更有用。

我这里有两种方法:

  1. 在 main() 之前使用全局对象。

  2. 在 main() 的第一行使用静态类定义。

还有一个想法,就是(因为我使用 gcc)是使用attribute __constructor__ gcc 保留函数。

你有什么建议?

第 2 部分:为了进一步解决这个问题,我需要解耦这些类的开发。(这更像是一个代码库设计问题。)

也就是说,如果有人正在编写 classA 而其他人正在编写 classB,那么我们将有两个单独的文件,分别是 classA 和classB,定义并在他们的文件/模块中调用他们自己的构造函数。

这是一个示例代码,说明了我的想法:

class Init_myclass
{
public:
  Init_myclass(): myvar(10)
  {
    std::cout << __PRETTY_FUNCTION__ << ":" << myvar << std::endl;
  };
private:
  int myvar;
};

static Init_myclass TestInit; //Initializing object prior to main
int main ()
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  //Use the data populated by the Init_myclass constructor
  return 0;
}

在上面的代码中,将 Init_myclass 替换为 100 个类定义,例如 classA、classB 等。

另一种方法是使用文件中的单个构造函数来调用其他文件中定义的多个类构造函数,从内部。

下面的示例代码可能会帮助您理解我的想法:

class InitializeOne
{
public:
  InitializeOne(): myvar(10)
  {
    std::cout << __PRETTY_FUNCTION__ << ":" << myvar << std::endl;
    A bunch of constructors of other classes here();
    classA();
    classB();
    ....
  };
private:
  int myvar;
};

int main()
{
static InitializeOne TestInit;//Object after main
... //functions depending on data populated by Initialize constructor 
}

类的初始化顺序无关紧要,但必须在main之前或进入main时初始化。

哪种设计更可取,为什么?

我希望,我的问题是可以理解的。如果没有,请告诉我,我遗漏了哪些信息或过于简单/复杂等。

感谢您的回复和时间。

【问题讨论】:

  • 恕我直言,如果您的子系统需要依赖(至少有这么多)单例,那么您的子系统的设计就有问题(您没有进一步详细说明)。
  • 该子系统是第 3 方数据库引擎,而其他进程又会监视该引擎以获取相关数据。我同意,这确实是一个糟糕的设计(从泥球演变而来),但这就是它必须被批准进入代码库的方式。 :(
  • 好吧,我已经猜到了。像这样。在这种情况下,您应该只提供一个单例类,它在它自己的实例化(构造函数)上调用所有必要的构造函数。换句话说:创建一个单例类,实例化所有需要在 main() 条目上实例化的类的成员,并访问您的单例实例一次。
  • 最后一个InitializeOne创建所有这些类,_并在main开始之前立即销毁它们。听起来这不是你想要的。
  • @MooingDuck:它将在 main() 开始之前删除?是静态的吧?

标签: c++ oop design-patterns object ooad


【解决方案1】:

如果可能,您应该选择方法 2。

创建一个单例类:

class InitializeOnce {

public:
    static InitializeOnce& getInstance()
    {
        static InitializeOnce theInstance;
        return theInstance;
    }

    virtual ~InitializeOnce() {}

    classA& getClassA() { return classA_; }
    classB& getClassB() { return classB_; }

private:
    classA classA_;
    classB classB_;

    InitializeOnce()
    : classA_()
    , classB_()
    {
    }

    InitializeOnce(const InitializeOnce& rhs); // Prohibit copying!
    InitializeOnce& operator=(const InitializeOnce& rhs); // Prohibit assigning!
};

... 并从 main 访问一次:

int main()
{
    static InitializeOnce& theInstance = InitializeOnce::getInstance();

    // ... functions depending on data populated by Initialize constructor 
}

在方法 1 的情况下,这将是:

static InitializeOnce& theInstance = InitializeOnce::getInstance();

int main()
{

   // ... functions depending on data populated by Initialize constructor 
}

注意
您提出的方法将导致不同的行为,因为函数局部静态变量保证在至少第一次访问它们之前被实例化,如果你真的需要访问它 before main() 被调用,你必须选择方法1。

恕我直言,应该避免您的第三个想法,编译器特定的属性定义(即使它是 gcc)会使代码的可移植性降低。

【讨论】:

  • 我不认为 local 静态变量保证在函数开始之前被初始化
  • @MooingDuck 谢谢,你是对的,这些只保证至少在函数被调用时被初始化一次。我会纠正这个...
  • void foo() { if (0) { static int a = 100; std::cout &lt;&lt; a;}} a 被初始化过。
  • § 6.7/4 “所有具有静态存储持续时间或线程存储持续时间的块范围变量的零初始化在任何其他初始化发生之前执行。具有静态的块范围实体的常量初始化存储持续时间,如果适用,在第一次进入其块之前执行。[Snip]。否则,此类变量在控件第一次通过其声明时被初始化;此类变量在其初始化完成时被视为已初始化。"跨度>
  • @MooingDuck ...表示'变量被访问'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 2018-11-27
相关资源
最近更新 更多