Les types de référence C++ comme variables d'instance sont interdits dans Objective-C++. Comment puis-je contourner cela?Type de référence C++ comme variable d'instance dans Objective-C++
Répondre
Vous ne pouvez pas utiliser raisonnablement les références comme variable d'instance car il est impossible d'initialiser les variables d'instance et les références ne peuvent pas être réinstallées.
Une alternative pourrait être simplement d'utiliser des pointeurs (éventuellement intelligents) à la place.
Une autre possibilité que vous se rapproche de C++ - comme le comportement est d'utiliser un membre de style PIMPL pour vos membres C++:
struct CppImpl {
SomeClass& ref;
CppImpl(SomeClass& ref) : ref(ref) {}
};
@interface A : NSObject {
CppImpl* pimpl;
}
- (id)initWithRef:(SomeClass&)ref;
@end
@implementation
- (id)initWithRef:(SomeClass&)ref {
if(self = [super init]) {
pimpl = new CppImpl(ref);
}
return self;
}
// clean up CppImpl in dealloc etc. ...
@end
boost :: ref() peut vous aider?
Pas vraiment - 'reference_wrapper
Une solution plus générique est d'utiliser reference_wrapper<T>
au lieu d'un struct personnalisé. Le résultat final est similaire.
Ensuite, si vous avez seulement besoin de stocker un membre, vous n'obtenez pas beaucoup d'avantages sur les pointeurs en utilisant la structure ou ce wrapper. (Merci Georg!)
Je l'ai utilisé la réponse de Georg comme point de départ pour l'exemple:
// This bare interface can be used from regular Objective-C code,
// useful to pass around as an opaque handle
@interface A : NSObject
@end
// This interface can be shown to appropriate Objective-C++ code
@interface A (Private) // @interface A() if it's just for this class's .mm file
- (id)initWithRef:(SomeClass &)ref;
@property (readonly, nonatomic) SomeClass &ref;
@end
@implementation A {
reference_wrapper<SomeClass> *_refWrapper;
}
- (id)init {
// and/or throw an exception
return nil;
}
- (id)initWithRef:(SomeClass &)ref {
self = [super init];
if(self) {
_refWrapper = new reference_wrapper<SomeClass>(ref);
}
return self;
}
- (SomeClass &)ref {
// reference_wrapper<T> is implicitly convertible to T&
return *_refWrapper;
// This would also work:
// return _refWrapper->get();
}
- (void)dealloc {
delete _refWrapper;
}
@end
Ce modèle d'en-tête multiple est utile de passer autour d'une poignée opaque dans le code Objective-C, tout en fournissant Objective-C++ caractéristiques à quelques privilégiés (même si c'est juste l'implémentation de la classe objc).
Pourquoi ne pas stocker un pointeur (éventuellement intelligent) directement sur l'instance ici? Je ne pense pas que l'emballage vous apporte quelque chose dans ce scénario. –
Pourquoi pas en effet. En y réfléchissant, dans des situations aussi simples que l'exemple, je n'ai généralement stocké qu'un pointeur. –
première phrase de Georg est tout à fait correct:
Vous ne pouvez pas utiliser des références sensiblement comme variable d'instance, car il n'y a pas moyen d'initialiser les variables d'instance et les références ne peuvent pas être remis en place.
Mais je ne pense pas que sa solution soit la meilleure.
La différence sémantique entre un pointeur et une référence est faible. Une référence est essentiellement un pointeur qui ne peut pas être nul. Donc c'est certainement une bonne idée d'utiliser des références dans votre interface pour rendre évident qu'un nullptr
n'est pas un argument d'initialisation valide. Mais en interne, vous pouvez simplement stocker un pointeur:
@interface A : NSObject {
SomeClass* p;
}
- (id)initWithRef:(SomeClass&)ref;
@end
@implementation A
- (id)initWithRef:(SomeClass&)ref {
if(self = [super init]) {
p = &ref;
}
return self;
}
@end
Il n'y a pas plus (dans le pire des cas: manuel) l'allocation de mémoire, pas la gestion des ressources du tout, pas indirection supplémentaire, etc. Chaque membre A peut affirmer simplement que p != nullptr
.
Affirmer dans chaque membre de A semble lourd et sujette aux erreurs, si vous pouvez préférer des modèles qui vous obligent à affirmer/vérifier une seule fois. –
Ce n'est pas différent que d'affirmer que votre pointeur pimpl est toujours valide dans chaque membre. Peut-être que c'est trop paranoïaque, mais cela s'applique aux deux solutions. – Sebastian
- 1. Type de référence non transmis comme référence
- 2. C# passage simple comme référence
- 3. Pourquoi utiliser var comme variable de type
- 4. C++/CLI de référence variable
- 5. void * comme type de variable inconnue
- 6. Reliure ObjectiveC classe C# problème
- 7. Clarification de la variable de référence C++
- 8. Type de référence de chaîne C#?
- 9. C# Type de référence de propriété?
- 10. Vérification C++ du type de référence
- 11. Personnalisation de writeToFile dans ObjectiveC
- 12. Analyseur AMF0 dans ObjectiveC
- 13. C++ - utiliser dynamiquement référence ou variable locale
- 14. Arguement Variable Avec Référence de la classe Comme 1er paramètre
- 15. javascript variable référence/alias
- 16. « System.Data.SQLite » comme référence
- 17. variable de référence
- 18. MVC utilisé dans la programmation ObjectiveC
- 19. Clonage d'un type de référence C# vers un type de référence dérivé
- 20. alloca et ObjectiveC Garbage Collector
- 21. C#: Enregistrer un type de classe dans une variable?
- 22. Equivalent du type de référence C++ en C#
- 23. utilisant C# type comme générique
- 24. déduction de type de modèle de référence
- 25. Utiliser la valeur variable comme un type de Scala
- 26. Combine chaîne en ObjectiveC
- 27. Comment traiter une variable d'instance comme une instance d'un autre type dans C#
- 28. Convertir le type par référence C# en le type correspondant non par référence
- 29. Utilisation d'enum comme argument de type de modèle dans C++
- 30. Type de valeur et type de référence
ouais, c'est tout! –
Je ne vois pas pourquoi vous ne stockez pas simplement un pointeur sur SomeClass lui-même. La différence entre une référence et un pointeur est (surtout) une sémantique que votre interface transporte parfaitement. Vois ma réponse. – Sebastian
@Sebastian Ceci est discutable si vous init avec un seul membre (à quelle fréquence avez-vous seulement un membre?). Cela devient intéressant si vous initiez avec plus d'un membre et souhaitez revenir à un comportement déterministe correct. FWIW, j'ai mentionné les pointeurs et cette approche comme options possibles. –