2009-12-18 13 views

Odpowiedz

4

liczba obiektów na co? Jeśli chcesz policzyć liczbę obiektów określonej klasy, możesz użyć statycznego licznika. Coś jak poniżej .. licznik Przyrost na tworzenie i ubytek while zniszczenie ..

class A 
{ 
    public: 
    static int counter; 
    A() 
    { 
     counter ++; 
    } 
    virtual ~A() 
    { 
     counter --; 
    } 
}; 

int A :: counter = 0; 
+0

Jak śledzić, czy obiekt jest tworzony przy użyciu malloc? –

+0

@KranthiKumar It * is not * 'created by malloc() '.' Jest * przydzielany * statycznie lub przez 'nowy' lub na stos; jest * skonstruowany * przez jednego z jego konstruktorów; i jest niszczony przez jego destruktor. – EJP

0

Można by utworzyć zmienną licznik do publiczności: od swojej klasie (zakładając tutaj mówisz zliczanie obiektów z utworzonej klasie)

class Widget { 
public: 
    Widget() { ++count; } 
    Widget(const Widget&) { ++count; } 
    ~Widget() { --count; } 

    static size_t howMany() 
    { return count; } 

private: 
    static size_t count; 
}; 
// obligatory definition of count. This 
// goes in an implementation file 
size_t Widget::count = 0; 

Zrobione z ddj.com

+0

powinieneś przeczytać cały artykuł od scott meyers, aby przekonać się, że te rozwiązania nie są najlepsze. Na końcu artykułu opisuje podejście szablonowe wspomniane w innych postach. –

27

Tworzenie klasy szablonu ze statycznego licznika.

Każdy obiekt w aplikacji rozszerzy tę klasę szablonów.

Gdy konstruktor jest nazywany przyrostem licznika statycznego (zmienna statyczna przypada na klasę - współdzielona przez wszystkie obiekty tej klasy).

Na przykład patrz obiekt licznika za pomocą Curiously recurring template pattern:

template <typename T> 
struct counter 
{ 
    counter() 
    { 
     objects_created++; 
     objects_alive++; 
    } 

    virtual ~counter() 
    { 
     --objects_alive; 
    } 
    static int objects_created; 
    static int objects_alive; 
}; 
template <typename T> int counter<T>::objects_created(0); 
template <typename T> int counter<T>::objects_alive(0); 

class X : counter<X> 
{ 
    // ... 
}; 

class Y : counter<Y> 
{ 
    // ... 
}; 

Wykorzystanie dla kompletności:

int main() 
{ 
    X x1; 

    { 
     X x2; 
     X x3; 
     X x4; 
     X x5; 
     Y y1; 
     Y y2; 
    } // objects gone 

    Y y3; 

    cout << "created: " 
     << " X:" << counter<X>::object_created 
     << " Y:" << counter<Y>::object_created 
     << endl; 

    cout << "alive: " 
     << " X:" << counter<X>::object_alive 
     << " Y:" << counter<Y>::object_alive 
     << endl; 
} 

wyjściowa:

created: X:5 Y:3 
alive: X:1 Y:1 
+0

Witam. Ładne podejście. Nigdy o tym nie wiedziałem. Dzięki! – bdhar

+0

Jakiś czas temu robiłem jakiś statyczny polimorfizm i natknąłem się na ten przykład, bardzo mi się podoba, a statyczny polimorfizm też jest fajny ... – stefanB

+0

Ładne rozwiązanie, mam jednak wątpliwości ... czy naprawdę konieczne jest wykonanie destruktora wirtualny w szablonie klasy podczas używania CRTP? Martwię się tylko o niewielki rozmiar spowodowany przez v-tables .. – Naveen

10
template <class T> 
class Counter 
{ 
    private: 
     static int count; 
    public: 
    Counter() 
    { 
     count++; 
    } 
    Counter(const Counter &c) 
    { 
     count++; 
    } 
    ~Counter() 
    { 
     count--; 
    }  
    static int GetCount() { 

     return count; 
    } 
} 

template<class T> 
int Counter<T>::count = 0; 



class MyClass : private Counter<MyClass> 
{ 
    public: 
     using Counter<MyClass>::GetCount; 
} 

Ta technika nazywa CRTP

+3

@stefanB, To jest prawidłowe podejście. Musisz mieć konstruktora kopii w Counter. – Jagannath

+1

+1, podejście stefanB nie obsługuje "X x2; X x3 = x2; '. Ale nie można zainicjować takiej liczby, ponieważ nie jest ona stała. – KeatsPeeks

+0

ya u r correct ... i hv, aby zdefiniować to poza klasą. – Ashish

3

Musisz przeciążać nowych i usuwać operatorów , aby zliczyć alokację pamięci.

void * operator new (size_t size) 
{ 
    void * p = malloc (size); 
    num_allocations++; 
    return p; 
} 

void operator delete (void * p) 
{ 
    num_deletions++; 
    free (p); 
} 
+0

Myślę, że nowe [] i usuń [] również muszą być przeciążone, jeśli chcesz śledzić obiekty na stercie. – Ashish

+0

Tak, masz poprawne Mac. Po prostu próbowałem go uruchomić. Musisz przeładować każdą odmianę nowego, którego używasz. – DevDevDev

+0

czy to nie łamie kodu? delete powinno najpierw wywołać destruktor; – NoSenseEtAl

Powiązane problemy