comment mettre en œuvre la coulée à une classe de base privée en C ++
-
03-10-2019 - |
Question
Comment mettre en œuvre la coulée à une classe de base privée en C ++? Je ne veux pas utiliser hacks comme l'ajout d'un ami, etc. Définition de l'opérateur de coulée publique ne fonctionne pas.
EDIT:
Par exemple, j'ai:
class A {
//base class
}
class AX : private A {
//a child
}
class AY : private A {
//another specialized child
}
class B {
//base class
void do (A a) {//do
}
}
class BX : private B {
//a child
void do (AX a) {
B::do( static_cast <A> (a) );
}
}
class BY : private B {
//another specialized child
void do (AY a) {
B::do( static_cast <A> (a) );
}
}
EDIT2
Pourquoi dois-je faire cela?
Supposons que je dois définir une propriété qui est assez lourd et peut être de plusieurs types similaires (comme VelocityX VelocityY etc). Ensuite, je veux être en mesure d'avoir des classes qui peuvent avoir un ensemble de ces propriétés. Si je veux traiter ces propriétés, il est évident que je préfère les jetai à leur type de base que d'ajouter une mise en œuvre pour chaque variation. Je ne l'utilise l'héritage public, car il est préférable de jeter explicitement si nécessaire que d'avoir l'interface privée implicitement visible. Pas un vrai problème, mais je voudrais avoir une solution:)
La solution
Si la définition d'un opérateur de coulée publique ne fonctionne pas, vous pouvez essayer avec une fonction régulière:
class D: private B {
public:
B& asB() { return static_cast<B&>(*this); }
};
...
D d;
d.asB().methodInB();
...
Quoi qu'il en soit, quel est le point? Si dérive de D
privé de B
, alors vous ne sont pas censés utiliser un D
comme B
de l'extérieur.
Autres conseils
Vous pouvez simplement utiliser un plâtre de style C. Pas besoin de « hacks » ou « mises en œuvre ». il enroulant dans une fonction explicite au service du peuple « C-moulages de style sont mauvais »
template<typename Targ, typename Src>
typename boost::enable_if<boost::is_base_of<Targ, Src>, Targ>::type &
private_cast(Src &src) { return (Targ&)src; }
Pour que le coffre-fort de la distribution, vous devez vous assurer que Targ
est en fait une base privée ou publique. Cela se fait par boost::is_base_of
.
Bien sûr, vous devriez préférer les fonctions membres dans la classe dérivée respective qui renvoient le pointeur de base, au lieu de faire un casting. .
Définition de l'opérateur de coulée publique ne fonctionne pas.
Cela ne me fait pas de sens ... Pourquoi faire la classe de base privée du tout alors? Il suffit de le rendre public. La raison pour laquelle vos fonctions de conversion ne fonctionnent pas parce que la norme exige que les conversions implicites ne considèrent jamais les fonctions de conversion à une classe de base, la classe elle-même ou void
.
J'ai un cas d'utilisation pour cela; Je suis héritant d'une classe de base importante et volatile qui ajoute des fonctions tout le temps et presque jamais est la fonction de la classe de base va fonctionner correctement dans ma sous-classe, donc je hériterai privé.
Je pense qu'il est plus simple que de faire une fonction qui retourne la classe de base. Ci-dessous je liste un programme entièrement corrigé; s'il vous plaît essayer de compiler votre code avant de soumettre une question, puisque l'utilisation des identifiants comme « faire » que les noms de fonction est susceptible de rendre chaque compilateur malheureux .. :-(: - (
class A {
//base class
};
class AX : private A {
//a child
public:
A *ToA() { return this; }
};
class AY : private A {
//another specialized child
public:
A *ToA() { return this; }
};
class B {
//base class
protected:
void do_it (A a) {};
};
class BX : private B {
//a child
void do_it (AX a) {
B::do_it( *a.ToA() );
}
};
class BY : private B {
//another specialized child
void do_it (AX a) {
B::do_it( *a.ToA() );
}
};