Alternative à c++ statique méthodes virtuelles
En C++ n'est pas possible de déclarer une statique de la fonction virtuelle, ni jeter un non-statique de la fonction pour un style C pointeur de fonction.
Maintenant, j'ai une plaine ol' C SDK qui utilise des pointeurs de fonction fortement.
Je dois remplir une structure avec plusieurs pointeurs de fonction. J'avais l'intention d'utiliser une classe abstraite avec un tas de statique des méthodes virtuelles pures, et les redéfinir dans les classes dérivées et de remplir la structure avec eux. Il n'était pas jusque-là que j'ai réalisé que virtuel statique ne sont pas autorisés en C++.
Aussi ce C Sdk signature de fonction n'ont pas de userData param.
Est-il une bonne alternative? Le mieux je pense est de définir certaines des méthodes virtuelles pures GetFuncA(), GetFuncB(),... et de quelques membres statiques (FuncA()/FuncB() dans chaque classe dérivée, ce qui serait retourné par la GetFuncX(). Ensuite, une fonction dans la classe abstraite pourrait appeler ces fonctions pour obtenir les pointeurs et remplir la structure.
Modifier
Répondre à Jean Dibling, il serait bon d'être en mesure de le faire:
class Base
{
FillPointers() { myStruct.funA = myFunA; myStruct.funB = myFunB; ...}
private:
CStruct myStruct;
static virtual myFunA(...) = 0;
static virtual myFunB(...) = 0;
};
class Derived1 : public Base
{
Derived1() { FillPointers(); }
static virtual myFunA(...) {...};
static virtual myFunB(...) {...};
};
class Derived2 : public Base
{
Derived2() { FillPointers(); }
static virtual myFunA(...) {...};
static virtual myFunB(...) {...};
};
int main()
{
Derived1 d1;
Derived2 d2;
//Now I have two objects with different functionality
}
- Il y a une bonne raison statique des fonctions virtuelles ne sont pas autorisés. Si vous avez une classe qui contient des fonctions virtuelles pures, il devient abstrait. Une classe abstraite ne peut pas être instanciée, donc il n'y a pas de risque de ces fonctions appelées. Toutefois, si vous permettez statique virtuals, ils pourraient être appelés à partir de la classe avec son instanciation. Il n'y aurait rien pour les empêcher d'être appelée avant qu'ils ont été définis!
- L'idée d'un
static
fonction est directement opposée à l'idée d'une purevirtual
fonction. Peut-être que si vous l'avez expliqué ce que vous cherchiez à atteindre plutôt que la façon dont vous étiez en train de la réaliser, nous pourrions vous donner de meilleurs conseils. - Le C SDK passer un contexte pointeur de fonctions? Sinon, avez-vous seulement besoin d'avoir un gestionnaire d'actif à un moment?
- Pouvez-vous poster le code que vous souhaitez écrire, mais ne peut pas car il n'y a pas une telle chose comme un
static virtual
? - Simple: initialiser les pointeurs dans les classes dérivées' CTors. Ce n'est pas vraiment beaucoup de code supplémentaire.
- Je n'ai pas l'obtenir. Ce que vous avez posté est juste plain ol' des fonctions virtuelles. Supprimer la
static
mot-clé et tout doit être beau. Je suis absent pourquoi vous pensez que vous avez besoinstatic
? - FillPointers() { myStruct.funA = myFunA; myStruct.funB = myFunB; ...} Ce qui ne compile pas moins que myFunA et myfunB sont statiques.
- Dibling - les méthodes virtuelles sont censés être appelée par du code C. C ne peut pas appeler C++ méthodes virtuelles, mais il peut appeler des méthodes statiques.
- Résolu. Quelqu'un a posté quelque chose sur les PFI, mais avant, j'ai réussi à lire attentivement elle j'ai mis à jour la page et il a été supprimé. Toutefois, la wikipédia m'a donné les détails manquants. Maintenant, je me demande quelle réponse dois-je accepter -_-
- Poster une réponse avec un lien vers l'article de Wikipedia sur la PFI et accepter votre propre réponse si vous pensez que c'est le meilleur...
- Err .. je ne vois pas ce que le PROGRAMME a à faire avec des fonctions virtuelles. L'curieusement récurrents pattern template est sur le moment de la compilation polymorphisme , pas de polymorphisme d'exécution.
- Oneal - Vous avez raison. PFI n'a rien à voir avec les fonctions virtuelles, mais depuis que les fonctions virtuelles peuvent pas être utilisés comme C rappels, et la question porte spécifiquement à l'aide de méthodes C++ que le C rappels, il est tout à fait approprié ici.
- Eh bien, fonctions membres statiques ne peuvent pas être de façon portable utilisé en tant que C-rappels soit.
- Oui, vous avez raison.
- des fonctions virtuelles pures sont un moyen d'obliger les descendants de fournir certaines choses pour la classe de base à utiliser. Depuis des fonctions virtuelles ne peuvent pas travailler dans ce cas, on peut utiliser une autre technique pour forcer les descendants de fournir certaines caractéristiques, à savoir, les PFI. Ma réponse démontre que. Je n'avais pas remarqué le supprimé de réponse quand j'ai posté le mien, mais je pense que ma réponse ne correspond mieux à démontrer dans le contexte de cette question, de toute façon (pas de conversion de type requis, et il construit une structure comme celle la C code exige).
- Peut-on m'expliquer ce qu':
ol'
signifie? - C'est une autre façon d'écrire "vieux".
Vous devez vous connecter pour publier un commentaire.
Vous pouvez faire
Base
être un modèle de classe qui prend ses pointeurs de fonction à partir de son argument de modèle:Ensuite, de définir les classes dérivées à descendre à partir d'une instanciation de
Base
à l'aide de chaque classe dérivée comme l'argument de modèle:Cette technique est connue sous le curieusement récurrents pattern template. Si vous négligez de mettre en œuvre l'une des fonctions dans une classe dérivée, ou si vous modifiez la signature de la fonction, vous obtiendrez une erreur de compilation, ce qui est exactement ce que vous vous attendez à obtenir si vous avez négligé de mettre en œuvre l'une des fonctions virtuelles pures à partir de votre plan d'origine.
La conséquence de cette technique, cependant, est que
Derived1
etDerived2
n'ont pas une classe de base commune. Les deux instanciations deBase<>
ne sont pas liés en aucune façon, autant que le système de type est concerné. Si vous avez besoin d'elles à être liée, alors vous pouvez introduire une autre classe afin de servir de base pour le modèle, puis mettre les choses en commun il y a:Attention: fonctions membres Statiques ne sont pas nécessairement compatibles avec des pointeurs de fonction. Dans mon expérience, si le compilateur accepte la cession déclarations ci-dessus, alors vous pouvez au moins être sûr qu'ils sont compatibles pour que le compilateur. Ce code n'est pas portable, mais si cela fonctionne sur toutes les plates-formes vous avez besoin de soutien, alors vous pourriez envisager il "assez portable."
extern C
. J'ai simplement pensé que si mon compilateur C++ accepté les déclarations de cession, alors qu'ils étaient au moins compatible avec mon système. Depuis, j'ai repris et mis à la structureextern C
, et le code fonctionne toujours. Testé sur le Soleil 5.8 et GNU 3.4.6 et 4.1.2. Tous les trois de compiler et d'exécuter sans avertissements ou des erreurs.Je pense que vous avez juste besoin d'utiliser une simple fonction virtuelle. Une statique de la fonction virtuelle n'a pas de sens, car une fonction virtuelle est résolu au moment de l'exécution. Ce qu'il y a à résoudre lorsque le compilateur sait exactement ce que la fonction statique est?
En tout cas, je vous suggérons de laisser la fonction pointeur de la solution en place, si possible. Baring que, considérez l'utilisation normale de la fonction virtuelle.
static
en premier lieu, ce n'est pas un plug dans la solution. Mais étant donné que votre question initiale ne contenait pas cette information, je pense que mon interprétation est une réponse raisonnable.Je peut encore voir une utilisation statique des méthodes virtuelles, voici un exemple:
Un modèle commun lors du passage d'un pointeur de fonction (un rappel) pour un C SDK utilise le fait que beaucoup de ces fonctions permettent à un void * paramètre "données utilisateur". Vous pouvez définir des rappels à de simples fonctions globales ou statiques fonctions de membre de classe. Ensuite, chaque rappel peut lancer les "données d'utilisateur" paramètre une classe de base pointeur de sorte que vous pouvez appeler une fonction membre qui effectue le travail de la fonction de rappel.
Vous pouviez juste passer les fonctions directement dans le constructeur de classe de base:
Si le type dérivé d'un objet peut être déterminée au moment de la compilation, vous pouvez utiliser le bouton "Curieusement Récurrents de Modèle de Modèle" à atteindre polymorphisme statique. Avec cette approche, vous n'êtes pas limité à seulement primordial quasi non-fonctions membres statiques. Statique et non-membres de fonction sont jeu juste. Vous pouvez même remplacer (mais la base de la taille de l'objet ne peut pas être une fonction de la ces types).
Voici le résultat:
Si le type dérivé ne peut être déterminé qu'au moment de l'exécution, il suffit d'utiliser un quasi non-statique de la fonction de membre de recueillir statique ou de non-fonctionnement d'infos sur l'objet ou de classe.
Ces choses serait certainement utile - à savoir, à force de tous les objets dans une hiérarchie de classe pour exposer une méthode de fabrique, au lieu d'un simple constructeur. Les usines sont très utiles pour vous assurer de ne jamais construire des objets non valides, une conception de garantir que vous ne pouvez pas appliquer presque aussi bien avec des constructeurs.
De construire des "virtuel statique" exige la construction de votre propre "statique v-table" à la main dans tous les objets qui en ont besoin. Virtuelle ordinaire des fonctions de membre du travail parce que le compilateur crée un secret tableau de pointeurs de fonction appelée la VTABLE dans toutes les instances de votre classe. Lorsque vous créez un "T" de l'objet, les pointeurs de fonction dans ce tableau sont affectés à l'une des adresses du 1er ancêtre de fournir l'API. Remplacement d'une fonction devient tout simplement le remplacement de l'original pointeur sur l'objet que vous obtenez à partir de "nouveaux" avec le nouveau prévu dans la classe dérivée. Bien sûr, le compilateur d'exécution et de gérer tout cela pour nous.
Mais, de retour dans le très vieux jours avant moderne du c++ (je me suis dit), vous deviez définir cette magie vous-même. Et c'est encore le cas pour la quasi statique. La bonne nouvelle c'est que cela - la vtable de vous construire à la main, pour eux, est en fait plus simple que le "ordinaires", les entrées ne sont pas plus chers en quelque manière que ce soit, y compris l'espace & performance que ceux pour les fonctions de membres. Il suffit de définir la classe de base avec un ensemble EXPLICITE des pointeurs de fonction (la statique de la vtable) pour l'Api vous souhaitez pris en charge:
Maintenant, chaque objet qui devrait prendre en charge une statique usine méthode peut être dérivé de cette classe. Ils tranquillement passer dans leur propre usine à leur constructeur, et il ajoute seulement 1 pointeur vers les objets qui en résultent tailles (comme à l'ordinaire VTable entrée).
Strousup et co. peut encore ajouter à cette idiomatiques motif à la base de la langue s'ils le voulaient. Il ne voulait même pas être si difficile que ça. Chaque objet dans une telle "C+++" serait tout simplement avoir 2 vtables au lieu de 1 - 1 pour les fonctions de membre de la prise de "cela" comme un argument et 1 pour le commun des pointeurs de fonction. Jusqu'à ce jour, cependant, nous sommes coincés avec manuel vtables tout comme l'ancien C-les programmeurs étaient dans les jours avant le c++.
En supposant que le C SDK vous permet de passer un void * à vos données, et vous devez passer votre ce pointeur de la classe dérivée:)
Si le C SDK ne permet pas de passer un pointeur à vos données qui est ensuite passé à vous par le biais de rappels, vous aurez bien du mal à faire cela. Depuis que vous avez indiqué dans un de vos commentaires que c'est effectivement le cas, vous êtes un peu hors de la chance. Je voudrais suggérer à l'aide de fonctions simples comme des rappels, ou la surcharge du constructeur et de la définition des méthodes statiques. Vous aurez toujours un moment difficile de déterminer quel est l'objet propre de vos méthodes sont censés travailler avec lors de vos rappels sont invoquées par le code C.
Si vous publiez plus de détails sur le kit de développement, il pourrait être possible pour vous donner plus de suggestions pertinentes, mais dans le cas général, même avec des méthodes statiques, vous devez trouver un moyen d'obtenir un ce pointeur de travailler avec.
Fonctions virtuelles sont essentiellement des pointeurs de fonction sous le capot. Ils suffit de pointer vers des fonctions différentes pour les différentes classes. Pour simuler virtuel-le comportement de la fonction, avoir un pointeur de fonction stockée quelque part, puis de "remplacement" il vient de le réaffecter à certaines fonctions différentes.
Alternativement, vous pouvez tester cela, mais je pense que les interfaces ont assez bonne compatibilité binaire. Vous pourriez sortir avec exposant une interface C++ entièrement composée de fonctions virtuelles pures, tant que tous les paramètres et les types de retour de cohérence de format binaire (par exemple. C types). Ce n'est pas un standard, mais il peut être assez portable.
Le moyen le plus évident, c'est comme cela, avec
FillPointers
mis en œuvre dans chaque classe dérivée.Cependant, vous pouvez probablement d'éviter que l'utilisation de certains modèles de la magie...
Si le C SDK veut vous d'effectuer des opérations sans fournir un userdata, puis l'orientation de l'objet est probablement inutile, et vous devez juste écrire quelques fonctions. Autre chose, le temps de trouver un nouveau SDK.
voir aussi C++ statique des membres virtuels?