2017-08-09 2 views
0

J'ai une classe Controller conçue pour être héritée. Il dispose actuellement d'une name() méthode virtuelle pure, comme ceci:Attribut de nom disponible à la compilation et à l'exécution C++

class Controller { 
public: 
    virtual const std::string name() const = 0; 
} 

Le nom est vraiment une classe propriété, plutôt que d'une propriété d'instance. Il ne devrait pas changer entre les instances d'une sous-classe, donc vraiment, le virtuel n'est pas la meilleure chose à faire ici. Quoi qu'il en soit, j'ai maintenant rencontré un problème où j'ai besoin du nom à la compilation, dans une fonction template. Evidemment T::name() ne fonctionne pas, et parce que les sous-classes ne seront pas constructibles par défaut, je ne peux même pas le contourner avec T()::name().

Donc quelque chose doit changer, mais je ne peux pas trouver la meilleure façon de le faire. Je dois être en mesure d'accéder à son nom dans les situations suivantes:

  • à la compilation, quand j'avoir un type de sous-classe (par exemple T::name())
  • Lors de l'exécution, quand j'ai une instance d'une sous-classe (par exemple instance->name())
  • lors de l'exécution, quand j'ai un Controller* (par exemple pointeur vers la classe de base)

name() ne doit pas être la méthode, il peut être un attribut public, ou autre chose. Mais peu importe ce que j'essaie, je peux seulement sembler satisfaire 2 des 3 exigences ci-dessus.

Quelqu'un peut-il suggérer de bonnes approches pour résoudre ce problème?

+2

Que voulez-vous dire par "au moment de la compilation"? Quel genre de déclaration avez-vous besoin d'exécuter au moment de la compilation avec une chaîne? –

+0

Indice: [impossible] (https://stackoverflow.com/questions/27123306/is-it-possible-to-use-stdstring-in-a-constexpr) –

+0

Dans une fonction de modèle, je dois obtenir le nom du type passé. par exemple. 'template bool has_controller() const {... besoin de T :: name() ici ...}' – Kazade

Répondre

1

Malheureusement, vous ne pouvez pas déclarer une méthode statique virtuelle si quelque chose comme cela ne fonctionnerait pas:

struct BaseClass { 
    static virtual std::string name() =0; 
}; 

struct ChildClass { 
    static std::string name() { 
    return "my_name"; 
    } 
}; 

vous pouvez plutôt faire une méthode avec un nom légèrement différent:

struct BaseClass { 
    virtual std::string name() =0; 
}; 

struct ChildClass { 
    std::string name() { 
    return ChildClass::_name(); 
    }; 

    static std::string _name() { 
    return "my_name"; 
    } 
}; 

qui sera travailler avec les trois cas que vous décrivez:

ChildClass c; 
BaseClass& b = c; 
std::cout << ChildClass::_name() << std::endl; 
std::cout << c.name() << std::endl; 
std::cout << b.name() << std::endl;