【问题标题】:How to override a parent classes static variable如何覆盖父类静态变量
【发布时间】:2011-04-21 00:25:55
【问题描述】:

如何覆盖父类的静态变量。

所以我有父类

class DatabaseItem
{
   static int instanceCount;

   DatabaseItem()
   {
     instanceCount++;
   }
};

如果我有 2 个继承自 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?
};

EDIT回应cmets

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

所以:

    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 重写相同的代码....

【问题讨论】:

  • 为每个派生类创建一个静态的..不需要重写。
  • 您不覆盖它,但您可以通过在派生类中创建同名变量来隐藏它。
  • @Tomalak Geret'kal 如果我将 DatbaseItem 的变量设为虚拟会怎样?所以 virtual static unsigned int instanceCount; ?那么子分类器必须为此创建一个变量?
  • @Mack:函数成员可以是虚拟成员,而不是数据成员。
  • @Tomalak Geret'kal 感谢您的回复。有没有其他方法可以解决我的问题?

标签: c++ inheritance subclass


【解决方案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】:

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

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

    numPersonItemsPerson 实例的数量。 FoodItem 类也可以这样做。

    【讨论】:

      【解决方案3】:

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

      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 以供重用。这是很多额外的工作,几乎没有实际收获,除非你试图将自己限制在相对较少的实例中。

      【讨论】:

        猜你喜欢
        • 2013-10-27
        • 2014-07-22
        • 1970-01-01
        • 1970-01-01
        • 2010-10-10
        • 1970-01-01
        • 1970-01-01
        • 2016-03-03
        相关资源
        最近更新 更多