C++中使用构造函数和析构函数的对象计数器

Object counter in C++ using Constructor and Destructor

所以,我是新来的,如果我有任何错误,请多多包涵。

我是一名学习 C++ 的大学生,刚接触构造函数和析构函数。

我想做的是:我需要创建一个程序来维护对象的实时计数,即,无论何时创建或销毁 class 的对象,对象计数器都是 incremented/decremented 分别显示(无论如何这是我的逻辑,建议会让我感激不尽)。

这意味着创建一个静态变量,我想出了这个:

class objectCount
{
    protected:
    static int count;

    public:
    objectCount()
    {
        count++;
        cout<<"Object of type class created. \nNo. of objects of type class currently: "<<count<<endl;
    }

    ~objectCount()
    {
        count--;
        cout<<"Latest object of type class deleted. \nNo. of objects of type class currently: "<<count<<endl;
    }
};

int objectCount::count=0;

void main()
{
    int ch;
    clrscr();
    cout<<"--------------- || OBJECT COUNTER || ----------------"<<endl;

    do {
        cout<<"1. Create Object\n2. Delete Object\n3.Exit";
        cout<<endl<<"Enter your choice: ";
        cin>>ch;

        switch(ch)
        {
            case 1: objectCount();
                break;

            case 2: ~objectCount();
                break;

            case 3: break;

            default: cout<<endl<<"Invalid Choice.";
                break;
        };
    }while(ch!=3);
    getch();
}

所以,我以为我已经准备好了,但是 TurboC(是的,我的大学强制我们使用 TC,因此我别无选择,只能使用它)给了我一个错误"Case 2: ~objectCounter();" 部分(非法结构操作)。我翻阅了这些书,意识到我忘记了构造函数也需要一个对象声明。 (objectCount OC;)

但现在我对如何更改代码以使其正常工作感到困惑。

我需要它以便根据用户的选择创建一个对象,不。对象更新和打印,否则对象删除,没有。打印和更新的对象数,完成后退出。

我四处搜索,但通常人们发布示例只是声明有限数量的对象,例如 "objectCount c1; objectCount c2;" 并完成它,这不是我的情况。

尊敬的、善良的、温和的、知识渊博的社区中的任何人都可以帮助我吗?

编辑:理想输出:

--------------- || OBJECT COUNTER || ----------------
1. Create Object
2. Delete Object
3. Exit
Enter your choice:  1
Object of type class created. 
No. of objects of type class currently: 1 //Static variable incremented & displayed here.

1. Create Object
2. Delete Object
3. Exit
Enter your choice:  1
Object of type class created. 
No. of objects of type class currently: 2 //Static variable incremented & displayed here.

1. Create Object
2. Delete Object
3. Exit
Enter your choice:  2
Object of type class deleted 
No. of objects of type class currently: 1 //Static variable decremented & displayed here.

1. Create Object
2. Delete Object
3. Exit
Enter your choice:  3

编辑 2:我想我将按照 besc 的建议使用 100 个对象的数组,现在应该可以工作了。

但感谢大家的回答,是的,我一定会超越 TC 并学习真正的交易。

欢迎光临!

~objectCount() 的问题本质上是它说 "delete the objectCount object"... 而编译器说 "which one?" 如果你不以某种方式跟踪你创建的对象,你可能是 memory-leaking 那些对象。

与其直接调用构造函数和析构函数,我建议使用 newdelete 关键字。这些对 objectCount 指针进行操作,因此例如,您可以使用如下代码:

objectCount * my_object = new objectCount(); // allocates memory, calls constructor
delete my_object; // calls destructor, frees memory

这就是 memory-manage 单个 objectCount 对象的方法。要保留其中的许多对象,您可能需要维护一个数组或 std::vector 这些指针。

您的计数逻辑实现是正确的(只要您处于 single-threaded 场景中),但您的 main() 不正确。

case 1 的开关中,您所做的是创建一个未命名的临时 objectCount 对象,该对象会立即再次被销毁。您会看到 ctor 立即被调用,然后是对 dtor 的调用。为什么会立即销毁?因为你没有给它起名字。所以,这不是特别有用,但有效;虽然这显然不是你想要的。

case 2 无法编译,因为您在没有对象的情况下调用了 dtor。这里其实有两个问题。

(1) dtor 需要知道它应该销毁哪个 objectCount 对象。在这方面,它的行为与任何其他 non-static 成员函数一样。这会起作用:

// Creates an object, ctor gets called.
objectCount obj;

// Calls the destructor on obj.
// DO NOT DO THIS! See (2).
obj.~objectCount();  

(2) 在 C++ 中,只有极少数情况会显式调用 dtor。只要您处于学习 C++ 的早期阶段,它们就无关紧要。所以这是一个有效的规则:如果你明确地调用一个 dtor,你就错了。当一个对象死亡时,Dtors 被隐式调用。死亡的发生方式取决于您的对象的分配位置。

在堆栈上:

void func() {
    objectCount obj;
} // obj goes out of scope here: dtor is called

在堆上:

objectCount* obj = new objectCount;
// ...
delete obj; // dtor is called

尽可能选择堆栈,因为使用 new/delete 进行手动内存管理非常容易出错。

正如您在堆栈示例中所见,作用域由花括号定义。如果您需要对对象的生命周期进行更细粒度的控制,您可以使用一组“独立的”卷曲。 IE。您的 main() 可能如下所示:

//...

do {
    cout << "1. Create/destroy on the stack\n"
    cout << "2. Create/destroy on the heap\n
    cout << "3.Exit";
    cout<<endl<<"Enter your choice: ";
    cin>>ch;

    switch(ch)
    {
        case 1: {
            {
                // Note the standalone set of curlies.
                objectCount obj;
            }
            break;
        }

        case 2: {
            objectCount* obj = new objectCount;
            delete obj;
            break;
        }

        case 3: break;

        default: cout<<endl<<"Invalid Choice.";
            break;
    };
}while(ch!=3);

// ...

为了让你的 user-choices 明确地创建和销毁你需要在这里使用 new/delete。没有合适的范围可以提供相同的效果。但在你这样做之前,想想可能出错的地方。例如,如果用户决定连续创建两次……或连续删除两次,将会发生什么。

编辑:

要让用户创建和销毁任意数量的对象,您需要保留包含现有对象的列表,a.k.a std::vector。那时 TurboC 成为一个真正的问题,因为它早于 C++ 标准模板库 (STL),向量是其中的一部分。并且此时您不想自己实现 vector。

我只想说你们国家教育委员会的决定是多么令人难以置信地脑残,将 DOS 时代的 IDE 强加给你们。您不会以这种方式学习任何有用的 C++。如果你做 C++ 只是为了功劳,那就完成它,然后忘记经验。但是如果你对这门语言完全感兴趣,那就给自己买一个现代编译器和 IDE 并在你自己的时间做一些真正的 C++。你选择什么并不重要:免费版 Visual Studio、Clang 或 GCC with Qt Creator、Eclipse、CLion:任何东西都将在与 TurboC 完全不同的世界中发挥作用。 [叹气现在感觉好多了,那是我的胸膛;)。]

好的,如何解决您眼前的问题?让它更简单。使用一个 C-style fixed-length 拥有指向已创建对象的指针的数组和一个保存当前已分配对象数的变量。

// ... in main() outside the loop ...
// 100 objects should be enough for everybody :)
// DO NOT DO THIS IN REAL C++! Use std::vector instead!
objectCount* object_ptrs[100];
int current_max_idx = 0;

现在您可以使用 new/delete 创建和销毁最多 100 个对象,并在此过程中递增和递减 current_max_idx。确保在程序退出时 delete 所有剩余的对象,并记住数组是 zero-based,即 object_ptrs 的索引为 0 到 99。

还可以考虑从 ctor 和 dtor 中删除计数逻辑。这是多余的,因为 current_max_idx 变量执行相同的工作并且在 creation/destruction 上打印可以发生在 switch.