【问题标题】:Static Variables, Separate Compilation静态变量,单独编译
【发布时间】:2023-04-10 06:57:02
【问题描述】:

我写了一个程序,它都在一个文件中,方法在头文件中前向声明。该程序最初在一个文件中时运行良好。但是当我分离程序时,我不断地随机出现在头文件中声明的类之一的析构函数。

我的标题中有一个静态变量来计算特定类的对象数。每当我构造对象时,我都会增加这个变量。然后在我的析构函数中,我从那个变量中减去 1,检查它是否为 0(意味着它是最后一个对象)并做一些事情。有时值似乎关闭,我不知道为什么。我的应用程序中确实有随机调用,但我不明白为什么这会影响我上面描述的内容,谢谢。感谢您提供任何帮助或见解!

[更新]:有一个基类,它包含在头文件中实现的析构函数..,然后我有两个派生类,它们在它们的构造函数中递增静态变量.. 那我该怎么办?

我想要做的是:在我的标题中我有这个:

class A {
public:
    virtual ~A() {
        count --;
        if (count == 0) { /* this is the last one, do something */ }
    }

class B : public A {
public:
    B();
}

然后我在B班

B::B() { 
    count++;
}

我在哪里可以定义计数,这样我就不会得到误导性的计数?谢谢。

【问题讨论】:

  • 有时不加起来的原因是编译器会自动为你生成复制构造函数。默认的复制构造函数不会增加 count 变量。

标签: c++ file variables static


【解决方案1】:

您必须在 A(全部)中定义构造函数来增加计数。

请注意,除非您定义它们,否则编译器会自动生成以下四种方法:

  • 默认构造函数(如果没有定义其他构造函数)
  • 默认析构函数
  • 复制构造函数
  • 赋值运算符

以下代码会覆盖编译器默认值,以便您获得准确的计数。

 class A
 {
    static int count;

    public:
        A()   // Default constructor.
        {
            ++count;
        }
        A(A const& copy)  // Copy constructor/
        {                 // Note If you do not define it the compiler
            ++count;      // will automatically do it for you
        }
        virtual ~A()
        {
            --count;
            if (count == 0)
            {  // PLOP
            }
        }
        // A& operator=(A const& copy)
        // do not need to override this as object has
        // already been created and accounted for.
};

//// 在源文件中:

int A::count = 0;

【讨论】:

    【解决方案2】:

    你的静态变量是在哪里定义的?也许您不小心在头文件中定义了它,而内联使事情变得混乱(并且编译器没有捕获多个定义,这很奇怪,但您永远不会知道)。

    确保类静态变量恰好在一个翻译单元中定义。你这样定义它:

    int MyClass::static_var;
    

    这也是你放置初始化器的地方,如果有的话。

    【讨论】:

    • 嗨,在我的标题中,我有一个析构函数,需要调用 static_var。但是我还需要在我的构造函数中为我的两个派生类调用 static_var,那么我在哪里可以放置这一行?
    【解决方案3】:
    class A {
    public:
        virtual ~A() {
            count --;
            if (count == 0) { // this is the last one, do something }
        }
    protected:
        static int count;
    };
    
    class B : public A{
    public:
    B();
    };
    

    然后,您需要在一个且只有一个源文件中放入以下内容。它应该放在包含 A 类代码的源文件中。

    int A::count(0);
    

    您需要这样做,因为头文件声明将有一个名为 count 的变量,但没有为它分配任何存储空间。如果你没有把它放在源文件中,链接器会抱怨它没有找到。

    【讨论】:

      【解决方案4】:

      您能否详细说明“价值似乎已关闭”的含义?你有太多的建筑吗?破坏力不够?如果构造太多而破坏不够,则与静态无关。

      另外,静态变量是什么意思?您是指静态成员字段还是实际的静态变量?

      如果你只在头文件中声明了一个静态变量(我怀疑你这样做了),那么每个包含该头文件的 C 文件都会有一个单独的该变量实例(因为全局变量之前的静态意味着它是有限的到那个目标文件)。

      【讨论】:

      • 我的头文件中确实有静态变量,我还能把它放在哪里,因为我的析构函数是在头文件中定义的并且它使用该变量,谢谢。
      • @BobS,静态变量是类的一部分,还是类的块之外?您可能希望在课堂上使用它。此外,您需要在其中一个 .cpp 文件中定义 (?) 它,以便将其导出一次。
      • 我有一个基类,它包含在头文件中实现的析构函数..,然后我有两个派生类,它们在它们的构造函数中递增静态变量.. 那我该怎么办?
      • @BobS,请将您的代码(或相关部分)粘贴到您的原始问题中,以便我们准确了解您在做什么。谢谢。
      • @Bobs,我是第二个管理员,你能发布代码或者至少是课程的代码吗?我们正在尝试确定您的静态是作为成员还是作为全局变量编写的。正如我的回答所示,这些在 C++ 中具有不同的语义。
      猜你喜欢
      • 2023-03-03
      • 2018-03-21
      • 1970-01-01
      • 1970-01-01
      • 2022-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-02
      相关资源
      最近更新 更多