count class instances for every derived class

2019-04-04 05:12发布

is there any way to make all derived classes count their instances?How (write code in one of C++, C#, Java)?

Imagine I've got access to the root class (e.g. object), and every other class is (directly or indirectly) derived from this class. What I want is:

AnyDerivedClass.InstancesCount()

Problem is, one must keep track of count in static variable, but it is not possible to "inject" static variable into derived class from base class, this holds only for member variables. That is, I have to write something like:

class object 
{ 
 private static int count = 0; 
 protected object() { ++count; }
 protected ~object() { --count; } 
 public static InstancesCount() { return count; } 
};

class derived : object 
{
 private static int count = 0;
 public derived() { ++count; }
 public ~derived() { --count; }
 public static InstancesCount() { return count; }
}

This functionality is obviously repeated, and I cannot put it in base class. Note there are 2 ways of calculating: that if there are 7 instances of class derived1 and 8 instances of class derived2, there are (a) 15 instances of object or (b) 0 instances of object. I don't care which one, because I can't do neither (using reasonably practical means, e.g. imagine 100 classes, half of which are in library I cannot modify).

Of course, in theory it is possible to create map of (some run-type type identifier) => int count, and use ugly, slow, (run-time type)-based approach (at least in C#, Java).

Of course, if I can modify derived classes, I can use copy-paste (awful), macro (yeah I know), mixins (not in these languages) etc. But that is still real ugly.

This is specific problem, but It happened to me several times, that I'd like to be able to "inject" static member into derived class to solve problem elegantly.

Help much appreciated.

EDIT: thanks for good answer, in C++ it is possibly to use CRTP (Curiously recurring template pattern) as well, but not in C#/Java (no multiple inheritance). Of course, one must have access to derived classes and add this base class, so question remains (in case there is no other way, this looks best).

EDIT 2: looks impossible with current languages. static part of every class is not inheriting (and that's right), but there is no inheriting singleton associated with every class, so these kinds of problems cannot be solved so elegantly. To illustrate things, look at the following code: normal members and static members are current OOP languages feature, "singleton" (or whatever word would be) members are my suggestion/desire:

class Base
{
    static int sMemberBase;
    int memberBase;

    //my wish (note that virtual for methods is allowed!):
    singleton int singletonMemberBase;
};
class Derived : Base
{
    static int sMemberDerived;
    int memberDerived;

    //my wish (note that virtual for methods is allowed!):
    singleton int singletonMemberDerived;
};

//taken apart: (note: XYZStatic classes do not derive)
class Base { int memberBase; }
class BaseStatic { int sMemberBase; } BaseStaticInstance;
class Derived : Base { int memberDerived; }
class DerivedStatic { int sMemberDerived;  } BaseStaticInstance;
//note: Derived::sMemberBase is compile-time changed to Base::sMemberBase

//my wish: (note inheritance!)
class BaseSingleton { int singletonMemberBase; } BaseSingletonInstance;
class DerivedSingleton : BaseSingleton { int singletonMemberDerived; } DerivedSingletonInstance;

If anything like that would be present in language, solution for my question would be simple and elegant:

//with singleton members, I could write counter like this:
class object
{
    singleton int count;
    object() { ++count; }
    ~object() { --count; }
};

7条回答
成全新的幸福
2楼-- · 2019-04-04 06:09

I would use a template. This is in C++, by the way.

template<typename T> class object {
private:
    static int count;
public:
    object() { count++; }
    object(const object&) { count++; }
    ~object() { count--; }
    static int GetCount() { return count; }
};
template<typename T> int object<T>::count = 0;

RTTI solution:

class object {
    static std::map<std::string, int> counts;
public:
    object() { counts[typeid(*this).name()]++; }
    object(const object&) { counts[typeid(*this).name()]++; }
    ~object() { counts[typeid(*this).name()]--; }
    template<typename T> int GetObjectsOfType() {
        return counts[typeid(T).name()];
    }
    int GetObjectsOfType(std::string type) {
        return counts[type];
    }
};
std::map<std::string, int> object::counts;

RTTI is less invasive and allows run-time selection of the type to be queried, but the template has far less overhead and you can use it to count every derived class individually, whereas RTTI can only count the most derived classes individually.

查看更多
登录 后发表回答