• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Przeszukiwanie obiektów C++

Object Storage Arubacloud
0 głosów
786 wizyt
pytanie zadane 17 września 2017 w C i C++ przez StillLearning Nowicjusz (200 p.)
Czy jest możliwość przeglądania wszystkich obiektów danej klasy w C++? Chodzi o znalezienie obiektu o najniżej wartości jednego z parametrów.
3
komentarz 17 września 2017 przez 10kw10 Pasjonat (22,880 p.)
musisz miec jakis kontener tych obiektow

2 odpowiedzi

+1 głos
odpowiedź 17 września 2017 przez mokrowski Mędrzec (155,460 p.)
wybrane 5 października 2017 przez StillLearning
 
Najlepsza

Najszybciej chyba CRTP. Dwa rodzaje interfejsów. Przez klasę zliczającą i przez obiekt. Oczywiście jeszcze można wiele poprawić ale to dość wygodne w kodzie pokazywać explicite obiekty jakich klas są interesujące oraz dostawać się z dowolnej instancji do innych instancji :-)

#include <iostream>
#include <set>
#include <string>

template<class T>
class ClassCounter {
public:
    static size_t countInstances() {
        return instances.size();
    }

    static const std::set<const T*>& getInstances(){
        return instances;
    }

    size_t countObjects() const {
        return ClassCounter<T>::instances.size();
    }

    const std::set<const T*>& getObjects() const {
        return ClassCounter<T>::instances;
    }

protected:
    ClassCounter() = default;
    static bool addInstance(const T* instance) {
        return instances.insert(instance).second;
    }

    static void removeInstance(const T* instance) {
        auto it = instances.find(instance);
        if(it != instances.end()) {
            instances.erase(it);
        }
    }

private:
    static std::set<const T*> instances;
};

template<class T>
std::set<const T*> ClassCounter<T>::instances;

class Animal: public ClassCounter<Animal> {
public:
    explicit Animal(const std::string& name): name{name} {
        addInstance(this);
    }

    ~Animal() {
        removeInstance(this);
    }

    friend std::ostream& operator<<(std::ostream& os, const Animal& animal) {
        os << "Animal: " << animal.name;
        return os;
    }

private:
    std::string name;
};

class Item: public ClassCounter<Item> {
public:
    explicit Item(const std::string& name): name{name} {
        addInstance(this);
    }

    ~Item() {
        removeInstance(this);
    }

    friend std::ostream& operator<<(std::ostream& os, const Item& item) {
        os << "Item: " << item.name;
        return os;
    }

private:
    std::string name;
};

int main() {
    // Access via static class...
    auto animal1 = Animal("Dog");
    auto animal2 = Animal("Cat");
    auto animal3 = Animal("Human");

    std::cout << ClassCounter<Animal>::countInstances() << " animal(s) in this zoo.\n";
    for(const auto& object: ClassCounter<Animal>::getInstances()) {
        std::cout << *object << '\n';
    }
    // Access via object...
    auto item1 = Item("Pen");
    auto item2 = Item("Car");
    auto item3 = Item("Chair");
    std::cout << item1.countObjects() << " item(s) in this box\n";
    for(const auto& object: item1.getObjects()) {
        std::cout << *object << '\n';
    }
}

PS. Delikatnie poprawiłem. Nie trzeba teraz pamiętać o jawnym wołaniu dodawania instancji. Robi to konstruktor klasy zliczającej. Nie trzeba także pamiętać o usunięciu obiektu. Robi to destruktor klasy zliczającej.

#include <iostream>
#include <set>
#include <string>

template<class T>
class ClassCounter {
public:
    using instances_container_t = std::set<const T*>;
    using objects_container_t = instances_container_t;

    static size_t countInstances() {
        return instances.size();
    }

    static const instances_container_t& getInstances(){
        return instances;
    }

    size_t countObjects() const {
        return ClassCounter<T>::instances.size();
    }

    const objects_container_t& getObjects() const {
        return ClassCounter<T>::instances;
    }

    ~ClassCounter() {
        removeInstance(static_cast<const T*>(this));
    }

protected:
    ClassCounter() {
        addInstance(static_cast<const T *>(this));
    }

private:
    static bool addInstance(const T* instance) {
        return instances.insert(instance).second;
    }

    static void removeInstance(const T* instance) {
        auto it = instances.find(instance);
        if(it != instances.end()) {
            instances.erase(it);
        }
    }

    static instances_container_t instances;
};

template<class T>
typename ClassCounter<T>::instances_container_t ClassCounter<T>::instances;

class Animal: public ClassCounter<Animal> {
public:
    explicit Animal(const std::string& name): name{name} { }

    ~Animal() { }

    friend std::ostream& operator<<(std::ostream& os, const Animal& animal) {
        return (os << "Animal: " << animal.name);
    }

private:
    std::string name;
};

class Item: public ClassCounter<Item> {
public:
    explicit Item(const std::string& name): name{name} { }

    ~Item() { }

    friend std::ostream& operator<<(std::ostream& os, const Item& item) {
        return (os << "Item: " << item.name);
    }

private:
    std::string name;
};

int main() {
    // Access via static class...
    auto animal1 = Animal("Dog");
    auto animal2 = Animal("Cat");
    auto animal3 = Animal("Human");

    std::cout << ClassCounter<Animal>::countInstances() << " animal(s) in this zoo.\n";
    for(const auto& object: ClassCounter<Animal>::getInstances()) {
        std::cout << *object << '\n';
    }

    // Access via object...
    auto item1 = Item("Pen");
    auto item2 = Item("Car");
    auto item3 = Item("Chair");
    std::cout << item1.countObjects() << " item(s) in this box\n";
    for(const auto& object: item1.getObjects()) {
        std::cout << *object << '\n';
    }
}

 

komentarz 17 września 2017 przez Ehlert Ekspert (212,670 p.)

CRTP to bardzo dobry pomysł zarówno do takich rzeczy jak i singletonuyes

komentarz 17 września 2017 przez mokrowski Mędrzec (155,460 p.)
Wprawdzie jest znana implementacja singletonu przez CRTP, ale i tak nie rozwiązuje problemu jego destrukcji. Ogólnie IMHO nie warto używać singletonu w C++ a zamiast niego warto użyć wzorca Monostate.
+2 głosów
odpowiedź 17 września 2017 przez Ehlert Ekspert (212,670 p.)
Korzystając z wzorców projektowych możesz sobie zrobić fabrykę, która będzie zawierać array wskaźników na wszystkie utworzone obiekty danego typu.

Podobne pytania

0 głosów
2 odpowiedzi 626 wizyt
pytanie zadane 11 maja 2016 w C i C++ przez sebask08 Użytkownik (510 p.)
0 głosów
2 odpowiedzi 366 wizyt
0 głosów
2 odpowiedzi 447 wizyt

92,547 zapytań

141,389 odpowiedzi

319,509 komentarzy

61,931 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...