c++中设计可以统计自身对象的类(1)
前天去滑雪,摔的惨不忍睹,腰酸背疼。休息了一天终于缓过劲儿来,把以前落下的功课补上吧。之前找软件方面的工作时经常被问到的一个问题:如何设计一个类,可以统计自身的对象,以及由它派生的对象的个数。当时胡乱说了一通,但是好像很多关键的地方没有注意。经过学习先写一下基本的思路,可能后续还会再写一篇用来完善。
首先设计一个可以统计自身对象个数的类,初步构想有这么几个特点:
1、包含一个静态变量作为储存当前对象的计数器;
2、在构造函数中对计数器作自加操作(包含拷贝构造函数),在虚构函数中对计数器作自减操作
3、拷贝构造函数实现深拷贝(内容拷贝),防止两个对象公用一块内存,因其中一个对象被析构后令一个对象也被删除(防止统计不准确,事实上很对时候统计不准确都与指针有很大关系)
根据以上特点我们设计如下类:
class cacu_self_num { private: static size_t num; //static const size_t max_num = 5; //其他数据成员 public: cacu_self_num(); cacu_self_num(cacu_self_num&); ~cacu_self_num(); static size_t get_object_num(); static void init(); protected: static void add(); static void min(); //static void set_max_num(size_t max); };
其实现如下:
#include"classLibrary.h" #include <iostream> //begin of defineing cacu_self_num class size_t cacu_self_num::num = 0; //const size_t cacu_self_num::max_num = 5; cacu_self_num::cacu_self_num() { ++num; //if(num>max_num)throw "实例化对象达到最大个数"; } cacu_self_num::cacu_self_num(cacu_self_num&)//拷贝构造函数 { ++num; //if(num>max_num)throw "实例化对象达到最大个数"; } cacu_self_num::~cacu_self_num() { --num; } size_t cacu_self_num::get_object_num() { return num; } void cacu_self_num::init() { num = 0; } void cacu_self_num::add() { ++num; } void cacu_self_num::min() { --num; } //end of defining cacu_self_num class
代码量比较少应该可以看懂,值得注意的是上面的第一条语句:
size_t cacu_self_num::num = 0;
这条语句将静态成员num的值初始化为零。请注意,不能再类声明中初始化静态成员变量,这是因为声明描述了如何分配内存,但是并不分配内存。对于静态变量来说,可以在类声明之外使用单独的语句来进行初始化,这是因为静态类成员变量时单独储存并由该类所有对象共享的,不是对象的组成部分。请注意,初始化语句指出了类型,并使用了作用域运算符,但是没有使用关键字static。初始化是放在方法文件中的而不是头文件,这样可以避免头文件被多次引用时多次初始化,从而引发错误。
最后来测试一下:
#include "classLibrary.h" #include<iostream> using namespace std; void test_of_static(void) { static int a = 0;//声明初始化语句只会执行一次 ++a; cout<<a<<endl; } int _tmain(int argc, _TCHAR* argv[]) { int counter = 0; cacu_self_num::init(); cacu_self_num* a = new cacu_self_num();//此处发现问题,如果写成for循环的形式,那么重复分配给一个指针空间,那么之前 cout<<a->get_object_num()<<endl; //分配的空间没有被回收,造成内存泄露 cacu_self_num* b = new cacu_self_num(); cout<<b->get_object_num()<<endl; //print_self_class* c = new print_self_class(); //cout<<b->get_object_num()<<endl; delete a; cout<<a->get_object_num()<<endl; delete b; cout<<b->get_object_num()<<endl; //delete c; //cout<<c->get_object_num()<<endl; cin>>counter; return 0; }
测试过程中发现了一个问题,如果将不同的初始化对象多次赋给一个对象指针,那么之前的对象变成内存垃圾,无法删除,造成内存泄露,目前还没找到解决方法。下一步学习便是解决该问题,并实现派生出来的该类也可以统计自身的个数(分开统计与总计都需要),并设置能够实例化对象的最大个数,并且实现精确统计。初步的简单类就先写到这里,且听下回分解!