如何覆盖父类的静态变量

时间:2011-04-21 00:25:56

标签: c++ inheritance subclass

如何覆盖父类静态变量。

所以我有父类

class DatabaseItem
{
   static int instanceCount;

   DatabaseItem()
   {
     instanceCount++;
   }
};

如果我有两个继承自DatabaseItem的类,我希望每个类都记录只存在多少个类的实例。我该怎么做?

所以:

class Person : public DatabaseItem
{
  // how do I make sure when I make the call  int numOfpeople = Person::instanceCount;
  // that I only get the number of people objects that exist & not all the DatabaseItem
  // objects that exist?
};

class FoodItem : public DatabaseItem
{
  // how do I make sure when I make the call  int numOffoodItems = FoodItem::instanceCount;
  // that I only get the number of FoodItem objects that exist & not all the DatabaseItem
  // objects that exist?
};

编辑回复评论

是的但是,上面只是一个例子,如果我这样做,那么我有很多重复的代码......

所以:

    class DatabaseItem
{
    public:
        static unsigned int instanceCount;
        static Vector <unsigned int> usedIDs;

        unsigned int ID;

        DatabaseItem()
        {
            ID = nextAvailableID();
            usedIDs.add( ID );
            DatabaseItem::instanceCount++;
        }

        DatabaseItem( unsigned int nID )
        {
            if ( isIDFree( nID ) )
            {
                ID = nID;
            }
            else ID = nextAvailableID();

            usedIDs.add( ID );
            DatabaseItem::instanceCount++;
        }

        bool isIDFree( unsigned int nID )
        {
            // This is pretty slow to check EVERY element

            for (int i=0; i<usedIDs.size(); i++)
            {
                if (usedIDs[i] == nID)
                {
                    return false;
                }
            }

            return true;
        }

        unsigned int nextAvailableID()
        {
            unsigned int nID = 0;

            while ( true )
            {
                if ( isIDFree( ID ) )
                {
                    return nID;
                }
                else nID++;
            }
        }
};


class Person    {
    public:
        static unsigned int instanceCount;
        static Vector <unsigned int> usedIDs;

        unsigned int ID;

        Person()
        {
            ID = nextAvailableID();
            usedIDs.add( ID );
            Person::instanceCount++;
        }

        Person( unsigned int nID )
        {
            if ( isIDFree( nID ) )
            {
                ID = nID;
            }
            else ID = nextAvailableID();

            usedIDs.add( ID );
            Person::instanceCount++;
        }

        bool isIDFree( unsigned int nID )
        {
            // This is pretty slow to check EVERY element

            for (int i=0; i<usedIDs.size(); i++)
            {
                if (usedIDs[i] == nID)
                {
                    return false;
                }
            }

            return true;
        }

        unsigned int nextAvailableID()
        {
            unsigned int nID = 0;

            while ( true )
            {
                if ( isIDFree( ID ) )
                {
                    return nID;
                }
                else nID++;
            }
        }
};

..然后我必须为FoodItem,coffeeRun ....重写相同的代码。

3 个答案:

答案 0 :(得分:1)

我认为在基类中不可能有一个静态变量,并告诉它每种类型的派生类实例有多少。相反,在每个类中都有一个静态类变量,它在构造函数中递增。

class Person : public DatabaseItem
{
     static int numPersonItems ;
     Person()
     {
         ++numPersonItems ;
     }
};

int DatabaseItem::numPersonItems = 0 ;

numPersonItemsPerson个实例的数量。同样可以为FoodItem类完成。

答案 1 :(得分:1)

使用模板来解决在每个构造函数等中更新实例计数的所有问题。

template<class T>
struct Instance
{
  static unsigned int count;
  Instance () { count ++; }
  Instance (const Instance& o) { count ++; }
};
template<class T>
unsigned int Instance<T>::count = 0;

现在,这个模板可以被任何类继承,您需要为它们的实例计算:

class DatabaseItem : public Instance<DatabaseItem> {};
class Person : public DatabaseItem, Instance<Person> {};
class FoodItem : public DatabaseItem, Instance<FoodItem> {};

就是这样!

每当声明一个类对象时,它就会完成它的工作。它可以用作以下内容:

DatabaseItem *pD = new DatabaseItem[5];
Person obj[10];
cout<<Instance<DatabaseItem>::count<<endl;  // 5 + 10 = 15
cout<<Instance<Person>::count<<endl;        // 10

您无需在任何地方更新计数。

答案 2 :(得分:0)

鉴于您不能依赖基类构造函数中的虚拟分派,您需要将静态信息作为参数直接提供给它,或者将派生类提供给它,以便它可以查询静态信息本身。后者如下图所示

struct Base { 
    //provide whatever actual interface you need your type to have here
    virtual ~Base();
};

template<typename Derived>
struct Intermediate : Base {
    Intermediate() {
        Derived::var++;  //doesn't rely on polymorphism so ok in constructor
    }
};

struct Derived : Intermediate<Derived> {
    static int var;
};

根据您的具体用例,我倾向于根本不这样做,并且要么基类将唯一ID分散到所有实例,而不管类型如何,或者将ID创建移动到单独的类/方法中直接,并查询它的唯一标识符:

template<typename T>
struct UniqueID { 
    static some64bitIntType GetID(); //possibly non-static, lots of ways to handle this
};

struct Object {
    some64bitIntType ID;
    Object() : ID(UniqueID<Object>::GetID()) { }
};

或者那些东西。就个人而言,我倾向于不打算重新发布ID以供重用。这是一项额外工作的很多,除非你试图将自己限制在相对较少的实例范围内,否则几乎没有实际收益。