Inici de sessió d'usuari


Barrejant les Característiques dels Llenguatges Objective-C i C++


En Objective-C, pots cridar mètodes des de qualsevol llenguatge en codi C++ i en mètode Objective-C. Els punters als objectes en qualsevol llenguatge són exactament punters, i així pots utilitzar-los a tot arreu. Per exemple, pots incloure punters a objectes Objective-C com dades membres de les classes C++, i pots incloure punters a objectes C++ com variables d'instí ncia de classes d'Objective-C. El Llistat 2-6 ho il·lustra.

Llistat 2-6. Utilitzant instí ncies C++ i Objective-C com a variables d'instí ncies

/* Hola.mm
 * Compila-ho amb: g++ -x objective-c++ -framework Foundation Hola.mm -o hola
 */

#import 
class Hola {
    private:
        id _text_salutacio;  // conté un NSString
    public:
        Hola() {
            _text_salutacio = @"Hola, món!";
        }
        Hola(const char* text_salutacio) {
            _text_salutacio = [NSString stringWithUTF8String: text_salutacio];
        }
        void diu_hola() {
            printf("%s\n", [_text_salutacio UTF8String]);
        }
}; 
@interface Salutacio : NSObject {
    @private
        Hola *_hola;
}
- (id)init; 
- (void)dealloc; 
- (void)saluda;
- (void)saluda:(Hola*)salutacio;
@end
@implementation Salutacio 
- (id)init {
    if (self = [super init]) {
        _hello = new Hola();
    }
    return self;
} 
- (void)dealloc {
    delete _hola;  
    [super dealloc];
} 
- (void)saluda {
    _hola->diu_hola();
} 
- (void)saluda:(Hola*)salutacio {
    salutacio->diu_hola();
} 
@end
int main() {
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    Salutacio *salutacio = [Salutacio new];
    [salutacio saluda];                         // > Hola, món!
        
    Hola *hola = new Hola("Hello, world!");
    [salutacio saluda:hola];                   // > Hello, world!
        
    delete hola;
    [salutacio release];
    [pool release];
    return 0;
}

Així com pots declarar estructures de C en interfícies d'Objective-C, també pots declarar classes C++ en interfícies Objective-C. Com amb les estructures C, les classes C++ definides dins una interfícies Objective-C estan en un abast global, no necessiten estar dins una classe d'Objective-C. (Això vé de la forma en que el C estí ndard -- al revés de C++ -- té la necessitat que les definicions d'estructures estiguin l'abast del fitxer).

Per permetre't que condicionis el teu codi basat en la variant del llenguatge, el compilador Objective-C++ defineix ambdues constants del coprocessador __cplusplus i __OBJC__, que són especificades (respectívament) en els llenguatges estí ndard C++ i Objective-C.

Com haurí s notat previament, l'Objective-C no permet que heredis classes C++ des dels objectes Objective-C, o a l'inrevés.

class Base { /* ... */ };
@interface ObjCClass: Base ... @end // ERROR!
class Derived: public ObjCClass ... // ERROR!

A diferència de l'Objective-C, els objectes de C++ estan definits estí ticament, amb un polimorfisme en temps d'execució disponible en algun cas excepcional. Els models d'objecte dels dos llenguatges no són directament compatibles. Més fonamentalment, el format dels objectes d'Objective-C i C++ en memòria són mútuament incompatibles, significa que és generalment imposible crear una instí ncia d'objecte que pugui ser ví lida des de la perspectiva d'ambdos llenguatges. D'aquí, que els dos tipus de jerarquies no poden barrejar-se.

Pots declarar una classe C++ dins una declaració de classe d'Objective-C. El compilador tracta cada classe com si estiguesin declarades en l'espai de noms global, de la següent manera:

@interface Foo {

class Bar { ... } // OK
}
@end

Bar *barPtr; // OK

L'Objective-C permet que les estructures C (tant si estan declarades dins d'una declaració d'Objective-C o no) siguin utilitzades com variables d'instí ncies.

@interface Foo {
struct CStruct { ... };
struct CStruct bigIvar; // OK
} ... @end

L'Objective-C de forma semblant procura permetre que les instí ncies de classes de C++ perveixin com a variables d'instí ncia. Això és posible més enllí que la classe C++ en qüestió (amb totes les seves superclasses) no tinguin definides cap funció mèmbre virtual. Si hi ha alguna funció membre virtual, la classe C++ pot no servir com una variable d'instí ncia d'Objective-C.

#import 

struct Classe0 { void foo(); };
struct Classe1 { virtual void foo(); };
struct Classe2 { Classe2(int i, int j); };

@interface Foo: NSObject {
 Classe0 classe0;    // OK
 Classe1 classe1;    // ERROR!
 Classe1 *ptr;       // OK-crida 'ptr = new Classe1()' des de Foo' init,
                     // 'delete ptr' des de Foo's dealloc
 Classe2 classe2;    // WARNING - constructor no cridat!
...
@end

El C++ requereix que cada instí ncia d'una classe que contingui funcions virtuals continguin un punter apropiar a la taula de punters de funcions virtuals. Encara que, l'execució de l'Objective-C no pot inicialitzar el punter de la taula de funcions virtuals, perqué no és familiar amb el model d'objecte d'Objective-C. De forma semblant, l'execució de l'Objective-C no pot servir crides a constructors o destructors C++ per aquests objectes. Si una classe C++ té algun contructor o destructor definit per l'usuari, aquests no seran cridats. El compilador emet una advertència en aquestos casos.

L'Objective-C no té noció de la necessitat dels espais de noms. No pots declarar classes d'Objective-C dins els espais de noms de C++, no pots declarar espais de noms dins de classe d'Objective-C.

Les classe d'Objective-C, els protocols, i les categories no poden declarar-se dins una "template" C++, una "template" C++ no pot declarar-se dins l'abast d'una interfície, protocol o categoria d'Objective-C.

Encara que les classes d'Objective-C poden servir com a parí metres d'una "template" C++. Els parí metres de les "template" C++ també poden utilitzar-se com a receptors o parí metres (encara que no com selectors) en expressions de misssatges d'Objective-C.