C++中使用构造函数和析构函数的对象计数器
Posted
技术标签:
【中文标题】C++中使用构造函数和析构函数的对象计数器【英文标题】:Object counter in C++ using Constructor and Destructor 【发布时间】:2017-01-21 19:33:10 【问题描述】:所以,我是新来的,如有错误请多多包涵。
我是一名正在学习 C++ 的大学生,并且不熟悉构造函数和析构函数。
我想要做的是:我需要创建一个程序来维护对象的实时计数,即,每当创建或销毁该类的对象时,对象计数器就会分别递增/递减并显示(无论如何,这是我的逻辑,建议会让我感激不尽)。
这意味着创建一个静态变量,我做了这个:
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,因此我没有其他选择但也可以使用它)给了我一个错误(非法结构操作)在“案例 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 并了解真正的交易。
【问题讨论】:
“是的,我的大学强迫我们使用 TC,因此我没有其他选择,但也可以使用它” 请务必稍后在 实际 C++,然后再寻找专业软件开发方面的工作。 “我四处搜索,但通常发布示例的人只是声明有限数量的对象,例如“objectCount c1(); objectCount c2();" 并完成它,这不是我的情况" 这些是函数声明,而不是对象。 “但现在我很困惑如何更改代码以使其正常工作。” 向量?当用户按下“1”时,将一个新对象添加到向量中。当用户按下“2”时,从向量中移除一个对象。太做作了,你没有很好地表达你的要求,所以我们不能给你一个正确的答案。至少,您的引用计数几乎是正确的,尽管您已经忘记了复制构造函数。 2017年使用TurboC++教学的真正意义是什么...现代编译器是免费的。 “虽然我猜这是因为我们将“计算机图形学”作为一个主题,并使用了 graphics.h 头文件,如果错了,请纠正我,它不在现代编译器中" 正确 - 现代编译器支持 实际 图形工具,而不是 1980 年代 DOS 版本的命令行模仿。令人难以置信的是,您的州教育委员会可能如此愚蠢。 【参考方案1】:您的计数逻辑实现是正确的(只要您停留在单线程场景中),但您的 main()
不正确。
在case 1
的开关中,您正在做的是创建一个未命名的临时objectCount
对象,该对象会立即再次被销毁。您会看到 ctor 立即被调用,然后是对 dtor 的调用。为什么会立即销毁?因为你没有给它起名字。所以,这不是特别有用,但有效;虽然这显然不是你想要的。
case 2
无法编译,因为您在没有对象的情况下调用 dtor。这里实际上有两个问题。
(1)
dtor 需要知道它应该销毁哪个objectCount
对象。在这方面,它的行为与任何其他非静态成员函数一样。这会起作用:
// 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);
// ...
要让您的用户选择明确地创建和销毁,您需要在此处使用 new/delete。没有合适的范围可以提供相同的效果。但在你这样做之前,想想可能出错的事情。例如,如果用户决定连续创建两次......或连续删除两次会发生什么。
编辑:
要让用户创建和销毁任意数量的对象,您需要保留一个包含现有对象的列表,即std::vector
。在这一点上,TurboC 成为一个真正的问题,因为它早于 C++ 标准模板库 (STL),vector 是其中的一部分。而且此时您不想自己实现向量。
我只想说,您的州教育委员会的决定是多么令人难以置信地脑死,将 DOS 时代的 IDE 强加给您。你不会以这种方式学习任何有用的 C++。如果您只是为了功劳而使用 C++,请完成它,然后忘记经验。但是,如果您对这门语言感兴趣,请为自己准备一个现代编译器和 IDE,并在自己的时间里做一些真正的 C++。你选择什么并不重要:免费版的 Visual Studio、Clang 或 GCC 以及 Qt Creator、Eclipse、CLion:任何东西都可以在与 TurboC 完全不同的世界中运行。 [叹息现在感觉好多了,我的胸膛已经消失了;)。]
好的,如何解决您眼前的问题?让它更简单。使用 C 风格的固定长度数组,该数组包含指向已创建对象的拥有指针和一个保存当前已分配对象数量的变量。
// ... 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
所有剩余的对象,并记住数组是从零开始的,即 object_ptrs
的索引为 0 到 99。
还可以考虑从 ctor 和 dtor 中删除计数逻辑。这是多余的,因为 current_max_idx
变量执行相同的工作,并且在创建/销毁时打印可以在 switch
中发生。
【讨论】:
好的,谢谢! “例如,如果用户决定连续创建两次......或连续删除两次会发生什么。” - 这就是我希望用户能够做的事情。例如。他创建了一个对象,o/p:“已创建对象,当前对象数:1”。他创建了另一个,o/p“对象已创建,当前对象数:2”。他现在决定删除,o/p:“对象已删除,当前活动的对象数量:1”。那种东西。 在答案中添加了理想的输出 修改了我的答案。 谢谢!我正在考虑类似的事情,但想知道是否有一种方法可以真正为用户提供无限的机会,尽管最终必须这样做。令人难以置信的是,对我来说,TC 是强加给我们的。虽然是的,但我确实很想学习游戏编码,比如 Unity w/C#,直到我对它的了解是 100% 完美的。我确实将 N++ 作为现代选项与 MinGW 挂钩,并且我在其中进行编码。 (虽然很少因为我没有足够的时间)。无论如何,我非常感谢你能忍受我和我的情况并给我一个可行的解决方案。我也会学习向量 事实上,到目前为止,我已经参加了完整的 Unity 开发课程并创建了一个简单的基于文本的“猜数字”游戏,其中游戏决定了一个数字。投注 0-100,并根据您的猜测为您提供提示,以帮助您猜出什么不是。它是。我添加了一些自己的代码(除了 tuts 中显示的代码)并关闭了所有松散的结尾并掩盖了所有可能的错误和场景。让我意识到 VS 中的 C# 比 DOS 提示屏幕上的 printf 有趣得多。附言我希望我在 SO 的自我广告条款的某些限制下评论这不是非法的。【参考方案2】:欢迎!
~objectCount()
的问题本质上是它说“删除 objectCount 对象”......而编译器说“哪个?”如果您不以某种方式跟踪您创建的对象,那么您可能会泄漏这些对象的内存。
我建议使用new
和delete
关键字,而不是直接调用构造函数和析构函数。它们对 objectCount 指针进行操作,例如,您可以编写如下代码:
objectCount * my_object = new objectCount(); // allocates memory, calls constructor
delete my_object; // calls destructor, frees memory
这就是内存管理单个 objectCount 对象的方法。要保留许多这些对象,您可能需要维护一个数组或这些指针的std::vector
。
【讨论】:
我强烈建议您不要使用new
和delete
。 “这就是内存管理单个 objectCount 对象的方法” 不,不是。也许是在 1985 年!
@Lightness:否则您将如何动态创建和销毁单个对象?是的,当然您可以将objectCount
实例存储在某个容器中,然后再次删除/销毁/弹出它们。但这不会分散当前课程的注意力吗?
@Lightness:unique_ptr
具有相同的特征,因此更难理解发生了什么。如果您知道自己在做什么,这是一个很好的工具。但如果你只是在学习,它会让人分心而没有明显的好处。
@IInspectable:Erm no RAII 使管理和理解变得更加容易,并且在很大程度上消除了搞砸的风险。 new
/delete
现在是高级功能。
@Lightness:如果不了解手动内存管理的风险,您将很难理解自动内存管理能给您带来什么。手动内存管理教给你两个重要的教训:1
很乏味而且容易搞砸。 2
就是内部使用的自动内存管理。以上是关于C++中使用构造函数和析构函数的对象计数器的主要内容,如果未能解决你的问题,请参考以下文章