Counting instances of individual derived classes

前端 未结 10 843
南笙
南笙 2021-01-06 04:42

I\'d like to be able to count instances of classes that belong in the same class hierarchy.

For example, let\'s say I have this:

class A;
class B: pu         


        
相关标签:
10条回答
  • 2021-01-06 04:48

    Create the classes through a factory so the factory will be able to keep track of how many have been created.

    Not as clean as just calling new on the class but it may do what you need.

    0 讨论(0)
  • 2021-01-06 04:55

    Directly off my head:

    • Create an integer static field in each class. Watch out for integer overflow.
    • Initialize it to 0 in an emulated static constructor.
    • Increment it at each (nonstatic) constructor body. Decrement it in the destructor.
    • GetInstancesCount() is a static function that returns the value of your integer static field.

    Note: See Mykola's comments. This would print 4 for A, 3 for B and 2 for C i.e. it would count one instance of B as "one A and one B", and one C as "one A, one B and one C". Which is in a way true, but is not what the question asks for. In other words, my answer is wrong :)

    0 讨论(0)
  • 2021-01-06 04:55

    A very crude way would be:

    class A
    {
    public:
        static int m_instanceCount;
        A(bool derivedInstance = false)
        {
            if(! derivedInstance)
            {
                ++m_instanceCount;
            }
        }
        virtual ~A()
        {
            --m_instanceCount;
        }
        virtual int GetInstanceCount()
        {
            return m_instanceCount;
        }
    };
    
    int A::m_instanceCount = 0;
    
    
    class B : public A
    {
    public:
        static int m_instanceCount;
        B(bool derivedInstance = false): A(true) 
        {
            if(! derivedInstance)
            {
                ++m_instanceCount;
            }
        }
        virtual ~B()
        {
            --m_instanceCount;
        }
        virtual int GetInstanceCount()
        {
            return m_instanceCount;
        }
    };
    
    int B::m_instanceCount = 0;
    
    
    class C : public B
    {
    public:
        static int m_instanceCount;
        C(): B(true) {++m_instanceCount;}
        virtual ~C()
        {
            --m_instanceCount;
        }
        virtual int GetInstanceCount()
        {
            return m_instanceCount;
        }
    };
    
    int C::m_instanceCount = 0;
    
    
    
    
    void main(int argc,char *argv[])
    {   
        A* p1 = new A;
        B* p2 = new B;
        C* p3 = new C;
        C* p4 = new C;
        A* p5 = new A;
    
        delete p5;
    
        std::cout<<p1->GetInstanceCount()<<"\n";
        std::cout<<p2->GetInstanceCount()<<"\n";
        std::cout<<p3->GetInstanceCount()<<"\n";
    }   
    
    0 讨论(0)
  • 2021-01-06 04:56

    This is a simple counter I use each so often for debugging:

    // counter.hpp
    #ifndef COUNTER_HPP
    #define COUNTER_HPP
    
    template <typename T>
    class Counter
    {
    public:
        Counter( bool do_count = true ) : counted(do_count) 
        { if ( counted ) get_count()++; }
        ~Counter() { if (counted) --count_; }
    
        static unsigned long count() { return count_; }
        static unsigned long& get_count() { 
           static unsigned long count=0;
           return count;
        }
    private:
        bool do_count;
    };
    #endif 
    

    The usage is simple, just inherit from it:

    class BaseClass : public Counter<BaseClass>
    {
    public:
       explicit BaseClass( bool do_count = true ) 
          : Counter<BaseClass>( do_count )
       {}
    };
    class DerivedClass : public BaseClass, Counter<DerivedClass>
    {
    public:
       explicit DerivedClass( bool do_count = true )
          : BaseClass(false), Counter<DerivedClass>(do_count)
       {}
    };
    

    User code will call a parameterless constructor:

    int main() {
       BaseClass b; // will call Counter<BaseClass>(true)
       DerivedClass d; // will call Counter<BaseClass>(false), Counter<DerivedClass>(true)
    }
    
    0 讨论(0)
  • 2021-01-06 04:58

    Use a static member variable for each class.

    struct A {
        A() { mInstances++; }
        ~A() { mInstances--; }
        static size_t mInstances;
        static size_t GetInstancesCount() { return mInstances; }
    };
    
    size_t A::mInstances;
    
    int main() {
        A* a = new A;
        A* aa = new A;
        cout << A::GetInstancesCount() << endl;
        delete a;
        delete aa;
        cout << A::GetInstancesCount() << endl;
        return 0;
    }
    
    0 讨论(0)
  • 2021-01-06 05:03

    The current solutions all seem to count in constructors, and therefore also count in constructors of base type. (except Mykola, but that solution has an implicit conversion from bool - bad) This double-counting wasn't desired. The tricky part, though, is that during the construction of a derived type, the object temporary has intermediate base types. And with virtual base classes, this situation is even worse. In that case, the intermediate type isn't even well-defined.

    Ignoring such transients, there are a few solutions to the double-counting:

    • Use a flag to disable counting
    • Use a protected base class constructor which doesn't count
    • Decrease the instance count of your base classes in derived constructors '*(this->base::count)--`
    • Keep the counts in a dedicated virtual base class.

    The latter option (virtual base class) is probably the nicest; the compiler will enforce it's initialized once and only once, from the final ctor.

    class counter {
        template<typename T> struct perTypeCounter { static int count =  0; }
        int* count; // Points to perTypeCounter<MostDerived>::count
    
        protected:
        template<typename MostDerived> counter(MostDerived*) 
        {
            count = &perTypeCounter<MostDerived>::count;
            ++*count;
        }
        ~counter() { --*count; }
    };
    
    0 讨论(0)
提交回复
热议问题