6
votes

Comment créer un tableau de classes en C ++?

Code:

Type inheritedTypesOfStruct[3] = {A, B, C};


13 commentaires

Vous voulez dire comme ça: vecteur v;


Voulez-vous un tableau des types eux-mêmes? Ou un tableau d'objets des types?


@BenjaminLindley: Évidemment, il veut un tableau de types. L'utilisation de base lorsque le type d'élément de tableau est trompeur, cependant.


Un tableau de types. J'ai besoin de cela, parce que je vais créer obj / struct de type aléatoire à l'avenir.


@Niklasbaumstark: Ce n'est pas évident pour moi. Beaucoup de gens ici ne communiquent pas efficacement leurs intentions, que ce soit parce qu'ils ne courent pas couramment la terminologie de programmation, ni ils ne courent pas couramment l'anglais.


@Benjaminlindley: Oui, vous parlez de la vérité là-bas.


J'ai édité la question pour faire le cas d'utilisation prévu un peu plus clair.


@Niklasbaumstark: semble beaucoup plus "évident" que ne veut pas veut un tableau de types, mais veut une gamme d'instances d'un type dérivé pour aller dans un tableau d'un type de base.


@Niklasbaumstark: Vous avez édité la question de la rendre plus claire sur ce que vous pense que l'étui d'utilisation prévu est. Laissons le point de faire ça, d'accord? Surtout que votre édition semble auto-conflictuelle ...


@ Tomalakgeret'kal: Op a dit dans un commentaire ce qu'il veut atteindre, je viens de l'ajouter à la question. Aussi que voulez-vous dire par «auto-conflit»?


@Niklasbaumstark: Oh, alors il l'a fait. Sozzles. :)


@ Tomalakgeret'kal: Pas de problème. Ce n'est vraiment pas la meilleure pratique de modifier des questions pour y ajouter des informations, mais dans ce cas, je pensais que cela pourrait aider à déplacer la discussion à la bonne direction (comme les réponses ciblées jusqu'à présent envers le polymorphisme).


@Niklasbaumstark: Non, vous étiez absolument correct de le faire. Je manquerais le commentaire de l'Op.


5 Réponses :


-1
votes

Vous pouvez regarder ici: http://www.java2s.com /Code/cpp/class/ObjectArrayPolymorphism.htm

sur l'utilisation du polymorphisme en C ++.


1 commentaires

Question ne concerne pas le polymorphisme et les liens ne sont pas des réponses



0
votes

Je n'ai pas la question. Demandez-vous un tableau qui peut contenir différents types d'instances en même temps? Cela est possible en utilisant le polymorphisme, bien sûr. Ou essayez-vous d'obtenir un tableau de types (comme la réflexion)? Ce serait possible d'utiliser des informations de type RTTI ou QT (à titre d'exemple), mais je n'ai jamais fait ça.


1 commentaires

Les demandes de clarification vont comme des commentaires, pas comme des réponses.



5
votes

Si votre compilateur prend en charge RTTI , vous pouvez faire quelque chose comme: xxx

Cependant, vous ne pourrez pas instancier une classe en utilisant uniquement son type_info . Le modèle d'usine pourrait être une meilleure réponse à votre problème racine.

< em> update: car type_info Les instances ne peuvent pas être copiées (leur constructeur de copie et son opérateur d'affectation sont privé ) et des tableaux de références sont illégaux, des pointeurs constants doivent être utilisé dans l'exemple ci-dessus.


0 commentaires

5
votes

Vous pouvez créer une gamme de fonctions, chacune desquelles renvoie un pointeur de base (ou un pointeur intelligent) que chaque pointe des objets de vos différentes classes dérivées. EG

typedef std::unique_ptr<Base> base_ptr;

template<typename Derived>
base_ptr CreateObject()
{
    return base_ptr(new Derived);
}

int main()
{
    std::function<base_ptr(void)> f[3] = {
        CreateObject<A>, CreateObject<B>, CreateObject<C>
    };

    base_ptr arr[10];
    for (int i=0; i<10; ++i)
        arr[i] = f[rand()%3]();
}


6 commentaires

J'essaie ton exemple, mais dans mon compilateur ne fonctionne pas: est un problème avec uniques_ptr


@Justi: essayez d'inclure l'en-tête . J'aurais dû faire cela quand même, cela vient de arriver que l'un des autres en-têtes l'a apparemment apportée. Si cela ne fonctionne pas, quel compilateur (et version) utilisez-vous? C'est une fonctionnalité C ++ 11, il est donc possible que votre compilateur ne le supporte pas, soit vous devrez peut-être définir des indicateurs. par exemple. Avec g ++, vous avez besoin -std = c ++ 0x . Si vous ne pouvez pas utiliser C ++ 11, FRET PAS, il existe d'autres solutions, mais essayons cela en premier.


J'ai l'environnement DVCPP par défaut. J'ajoute l'en-tête mais aucun résultat. Ajout au compilateur -std = C ++ 0x sans résultats positifs.


Je ne suis pas sûr de ce que compilateur devcpps utilise et, malheureusement, je n'ai pas le temps d'enquêter en ce moment. Essayez d'obtenir un compilateur moderne. Je sais bien sûr que Visual C +++ 2010 et Mingw prennent en charge le code ci-dessus hors de la boîte. Essayez d'en avoir un. Je serai de retour plus tard pour vérifier.


Malheureusement, l'utilisation de DVCPP a été imposée d'en haut. Thx pour vos réponses.


@Justi: Dans ce cas, vous pouvez utiliser des installations similaires fournies dans Boost, ici - ou vous pouvez utiliser des pointeurs de fonction. Exemple ici. Les pointeurs de fonction ne sont pas aussi polyvalents que std :: Fonction ou < Code> Boost :: Fonction , mais ils doivent travailler à vos fins. Notez également que je éteigniez les pointeurs uniques des pointeurs réguliers, au cas où vous n'aviez pas accès à ceux-ci. Votre compilateur n'a-t-il pas été plaint de cela aussi?



1
votes
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <map>
#include <vector>
#include <memory>

using namespace std;




// interface
class Base
{
public:
    virtual ~Base() { }
    virtual int getClassId() = 0;
};


// class A relizes interface Base, has ID == 1 (is used in automatic registration to factory)
class A : public Base
{
public:
    const static int ID = 1;
    static Base* CreateInstance()
    {
        return new A();
    }

    virtual int getClassId()
    {
        return ID;
    }

    virtual ~A() { }
};


// class B relizes interface Base, has ID == 2 (is used in automatic registration to factory)
class B : public Base
{
public:
    const static int ID = 2;
    static Base* CreateInstance()
    {
        return new B();
    }

    virtual int getClassId()
    {
        return ID;
    }

    virtual ~B() { }
};



// this is the objects factory, with registration only (unregister s not allowed)
class ObjectFactory
{
    ObjectFactory() { }
    ObjectFactory(ObjectFactory&) { }
public:
    virtual ~ObjectFactory() { }
    static ObjectFactory& instance()
    {
        static ObjectFactory objectFactory;

        return objectFactory;
    }

    typedef Base* (*Creator) ();

    void registerCreator(int id, Creator creator)
    {
        registry[id] = creator;
    }

    Base* CreateById(int id)
    {
        return registry[id]();
    }

private:
    map<int, Creator> registry;
};


// this template class is used for automatic registration of object's creators
template <class T>
struct RegisterToFactory
{
    RegisterToFactory(ObjectFactory& factory)
    {
        factory.registerCreator(T::ID, &T::CreateInstance);
    }
};


namespace
{
    // automaticaly register creators for each class
    RegisterToFactory<A> autoregisterACreator(ObjectFactory::instance());
    RegisterToFactory<B> autoregisterBCreator(ObjectFactory::instance());
}




// lets this this solution
int main(int argc, char *argv[])
{
    vector<int> ids;

    ids.push_back(static_cast<int>(A::ID));
    ids.push_back(static_cast<int>(B::ID));

    srand(time(0));

    for (int i = 0; i < 20; ++i)
    {
        int randomClasssId = ids[rand() % ids.size()];
        auto_ptr<Base> testObject(ObjectFactory::instance().CreateById(randomClasssId));
        cout << "Object of classId = " << testObject->getClassId() << " has been produced by factory." << endl;
    }


    system("PAUSE");
    return EXIT_SUCCESS;
}

2 commentaires

Si vous voulez protéger le créateur d'objet, déplacez le créateur statique à une section privée / protégée et rendez cette classe de classe à la classe de créateurs externe concrets. Cela peut être utile lorsque le processus de création est complexe et que l'erreur est enclinée. Le créateur externe possède des connaissances entière comment instancier correctement les objets de cette classe, de sorte que l'utilisateur final n'a jamais échoué ici.


Je ne recompose pas à l'aide de RTTI, sauf si vous connaissez la plate-forme en béton, et chaque module (DLL, librez-vous ....) a strictement le nom de la compilation et une option de liaison. Certains compilateurs plus anciens peuvent avoir des problèmes avec RTTI avec des espaces de noms et des enregistrements de module croisés à une telle usine surtout lorsque nous essayons d'enregistrer des classes de modèle. En général, RTTI est la semaine, essayez de ne pas l'utiliser, car RTTI peut être désactivé à la configuration du bâtiment et Nothig fonctionnera.