2010-11-07 10 views
0

Y at-il un moyen de le faire automatiquement pour toutes les classes dérivées, que je n'ai pas besoin de créer la fonction applyPack pour toutes les classes imbriquées.Comment peut-on faire cela automatique?

Ceci est mon morceau de code:

/** every class has registered id with this function */ 
template<typename T> 
uint getID() { 
    static uint id = registerClass<T>(); 
    return id; 
} 

class TemplatesPack { 
public: 
    template<typename T> 
    typename T::Template get(); 
}; 

class Object { 
public: 
    virtual void applyPack(TemplatesPack *p) { this->setTemplate(p->get<Object>()); }; 
}; 

class Object2: public Object { 
public: 
    void applyPack(TemplatesPack *p) { this->setTemplate(p->get<Object2>()); }; 
}; 

class Object3: public Object { 
public: 
    void applyPack(TemplatesPack *p) { this->setTemplate(p->get<Object3>()); }; 
}; 

class Object4: public Object2 { 
public: 
    void applyPack(TemplatesPack *p) { this->setTemplate(p->get<Object4>()); }; 
}; 

J'ai lu quelque chose au sujet des traits de caractères, mais je ne veux pas avoir la classe Object templated. Peut-on le faire avec C++ et modéliser certaines fonctions dans la classe TemplatesPack ou avec C++ 0x? s

+3

Qu'est-ce que vous essayez vraiment de faire? Je ne peux pas penser à un cas d'utilisation où ce que vous essayez de faire dans cette question est nécessaire. Il est possible qu'il existe un meilleur moyen d'atteindre votre objectif. –

Répondre

5

Modifier:
a modifié la réponse pour rendre l'objet intact.

template<class T> 
class Base<T> : public Object 
{ 
public: 
    virtual void applyPack(TemplatePack *p) { this->setTemplate(p->get<T>()); }; 
}; 

class Object2 : public Base<Object2> 
{ 
    // ... 
}; 

Edit: pour le cas de Object4, peut-être ce qui suit vous aidera:

template<class S, class D> 
class Base<S, D> : public S 
{ 
public: 
    virtual void applyPack(TemplatePack *p) { this->setTemplate(p->get<D>()); }; 
}; 

class Object2 : public Base<Object, Object2> { /* ... */ }; 

class Object3 : public Base<Object, Object3> { /* ... */ }; 

class Object4 : public Base<Object2, Object4> { /* ... */ }; 
+0

-1: OP ne veut pas que 'Object' soit une classe template. –

+1

-1: L'OP a dit qu'il ne voulait pas modéliser la classe, et, pire encore, cette approche signifie que 'Object2',' Object3', etc. seront dans des hiérarchies de classes non apparentées! –

+0

@downvoters: en effet. J'ai ajusté la réponse. – Vlad

1

Vous pouvez utiliser l'héritage virtuel et la règle de dominance, si vous ne voulez pas créer des modèles à Base

template<typename Derived, typename Base = void> 
struct applyer : virtual applyer<Base, typename Base::base_type> { 
    virtual void applyPack(TemplatesPack *p) { 
    dynamic_cast<Derived*>(this)->setTemplate(p->get<Derived>()); 
    }; 

    typedef Base base_type; 
}; 

template<typename Derived> 
struct applyer<Derived, void> { 
    virtual void applyPack(TemplatesPack *p) { 
    dynamic_cast<Derived*>(this)->setTemplate(p->get<Derived>()); 
    }; 
}; 

maintenant, vous pouvez le faire comme suit

class Object : virtual public applyer<Object> { 

}; 

class Object2: public Object, virtual public applyer<Object2, Object> { 

}; 

class Object3: public Object, virtual public applyer<Object3, Object> { 

}; 

Le deuxième argument est la classe de base directe, qui peut être omise s'il n'y en a pas. Par exemple, si vous dérivez de Object3, vous devez le faire comme suit:

class Object3_1: public Object3, virtual public applyer<Object3_1, Object3> { 

}; 
+0

Cela va-t-il coûter de la mémoire supplémentaire dans chaque objet? – kravemir

+0

Et puis-je utiliser cela dans plus de classes dérivées comme Object4? – kravemir

+0

@Miro vous devrez tester si elle utilise plus de mémoire. Je n'ai aucune idée. Cela fonctionne très bien avec Object4 (appelé "Object3_1" dans mon exemple parce que je l'ai écrit avant de modifier votre question). –