domenica 16 maggio 2010

Guida Objective-C in Italiano - C++ e Objective-C - Parte 15


Eccoci finalmente all'ultima parte della Guida all'Objective-C. L'argomento trattato oggi è l'uso di C++ e Objective-C.

Questo post è una traduzione in italiano della Guida all'Objective C, presente sul sito developer.apple.com a questo link. L'Objective C è il linguaggio di programmazione per creare applicazioni per iPhone. Questa guida potrebbe interessare a tutti gli sviluppatori che vogliono imparare le basi di questo linguaggio che è il fondamento per programmare nuove applicazioni per Mac Os X, iPhone ed iPad.


Usare C++ Con Objective-C

Il compilatore Objective-C di Apple ti permette di mixare liberamente C++ e Objective-C nello stesso file sorgente. Questo linguaggio ibrido Objective-C/C++ è chiamato Objective-C++. Con esso puoi fare uso di librerie C++ esistenti dalle tue applicazioni Objective-C.

Mixare Caratteristiche di Linguaggio Objective-C e C++

In Objective-C++, puoi chiamare metodi da l'uno o l'altro linguaggio, nel codice C++ e nei metodi Objective-C. I puntatori ad oggetti in uno o l'altro linguaggio sono solo puntatori, e come tali possono essere usati ovunque. Ad esempio, puoi includere puntatori a oggetti Objective-C come membri dati di classi C++, e puoi includere puntatori ad oggetti C++ come variabili di istanza di classi Objective-C.
Il listato 14-1 illustra questo.

Nota: Xcode richiede che i nomi dei files abbiano un'estensione ".mm" per le estensioni Objective-C++ per poter essere abilitate dal compilatore.

Listato 14-1 Usare C++ ed istanze Objective-C come variabili di istanza

/* Hello.mm

* Compila con: g++ -x objective-c++ -framework Foundation Hello.mm -o hello

*/



#import

class Hello {

private:

id greeting_text; // Contiene una NSString

public:

Hello() {

greeting_text = @"Hello, world!";

}

Hello(const char* initial_greeting_text) {

greeting_text = [[NSString alloc] initWithUTF8String:initial_greeting_text];

}

void say_hello() {

printf("%s\n", [greeting_text UTF8String]);

}

};



@interface Greeting : NSObject {

@private

Hello *hello;

}

- (id)init;

- (void)dealloc;

- (void)sayGreeting;

- (void)sayGreeting:(Hello*)greeting;

@end



@implementation Greeting

- (id)init {

if (self = [super init]) {

hello = new Hello();

}

return self;

}

- (void)dealloc {

delete hello;

[super dealloc];

}

- (void)sayGreeting {

hello->say_hello();

}

- (void)sayGreeting:(Hello*)greeting {

greeting->say_hello();

}

@end



int main() {

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];



Greeting *greeting = [[Greeting alloc] init];

[greeting sayGreeting]; // > Hello, world!



Hello *hello = new Hello("Bonjour, monde!");

[greeting sayGreeting:hello]; // > Bonjour, monde!



delete hello;

[greeting release];

[pool release];

return 0;

}

Come puoi dichiarare strutture C in interfacce Objective-C, puoi anche dichiarare classi C++ in interfacce Objective-C. Come con le strutture C, le classi C++ definite dentro un'interfaccia Objective-C hanno uno scope globale, non annidato entro la classe Objective-C. (ciò è coerente con il modo in cui standard C (sebbene non C++) promuova le definizioni di strutture nidificate allo scope del file).

Per permettervi di condizionare il vostro codice basato su una variante del linguaggio, il compilatore Objective-C++ definisce entrambe le costanti di preprocessore __clusplus e __OBJC__, come specificato dagli standards dei linguaggi C++ e Objective-C rispettivamente.

Come detto precedentemente, Objective-C++ non permette di ereditare classi C++ dagli oggetti Objective-C, nè permette di ereditare classi Objective-C da oggetti C++.
class Base { /* ... */ };

@interface ObjCClass: Base ... @end // ERROR!

class Derived: public ObjCClass ... // ERROR!

Diversamente dall'Objective-C, gli oggetti in C++ sono tipati staticamente, con polimorfismo a runtime disponibile come caso eccezionale. I modelli oggetto dei due linguaggi sono quindi non direttamente compatibili. Più fondamentalmente, il layout degli oggetti Obj-C e C++ in memoria è mutuamente incompatibile, ciò significa che generalmente è impossibile creare un'istanza di un oggetto che sarebbe valida dalla prospettiva di entrambi i linguaggi. Quindi, i due tipi di gerarchia non possono essere intercambiati.

Puoi dichiarare una classe C++ dentro una dichiarazione di calsse Objective-C. Il compilatore tratta queste classi come se fossero state dichiarate nel namespace globale, come segue:
@interface Foo {

class Bar { ... } // OK

}

@end



Bar *barPtr; // OK

Objective-C permette di usare strutture C (sia se dichiarate dentro una dichiarazione Objective-C sia se non dichiarate) come variabili di istanza.
@interface Foo {

struct CStruct { ... };

struct CStruct bigIvar; // OK

} ... @end

Su Mac OS X 10.4 e successivi, se imposti il flag del compilatore fobjc-call-cxx-cdtors, puoi usare istanze di classi C++ che contengono funzioni virtuali e costruttori non banali e decostruttori come variabili di istanza.( il flag fobjc-call-cxx-cdtors è impostato di default in gcc-4.2.) I Costruttori sono invocati nel metodo alloc (specificamente, dentro class_createInstance), in ordine di dichiarazione immediatamente dopo che l'oggetto di cui sono membri è allocato. Il costruttore usato è il "costruttore pubblico senza argomenti". I distruttori sono invocati nl metodo dealloc (specificamente, dentro object_dispose), in ordine inverso della dichiarazione immediatamente prima che l'oggetto di cui sono membri è deallocato.

Mac OS X v10.3 e precedenti: Le seguenti precauzioni si applicano solo a Mac OS X v10.3 e precedenti.

Objective-C++ in modo simile si sforza di permettere a istanze di classi C++ di servire come variabili di istanza. Questo è possibile fintanto che la classe C+ in questione non ha funzioni membro virtuali definite. Se qualunque funzione membro virtuale fosse presente, la classe C++ potrebbe non servire come una variabile d'istanza Objective-C.
#import



struct Class0 { void foo(); };

struct Class1 { virtual void foo(); };

struct Class2 { Class2(int i, int j); };



@interface Foo : NSObject {

Class0 class0; // OK

Class1 class1; // ERROR!

Class1 *ptr; // OK—call 'ptr = new Class1()' from Foo's init,

// 'delete ptr' from Foo's dealloc

Class2 class2; // WARNING - constructor not called!

...

@end

C++ richiede che ogni istanza di una classe che contiene funzioni virtuali contenga un puntatore adatto nella tavola delle funzioni virtuali. Comunque, il runtime dell'Objective-C non può inizializzare il puntatore della tavola delle funzioni virtuali, perchè non è familiare con il modello degli oggetti C++. In modo analogo, il runtime di Objective-C non può spedire chiamate a costruttori C++ o decostruttori per quegli oggetti. Se una classe C++ ha qualsiasi costruttore definito da utente o distruttore, essi non sono chiamati. Il compilatore emette un warning in tali casi.

Objective-C non ha una nozione di nasmespaces annidati. Non puoi dichiarare classi Objective-C dentro namespaces C++, nè puoi dichiarare namespaces dentro classi Objective-C.

Classi Objective-C, protocolli, e categorie non possono essere dichiarati dentro un template C++, nè un template C++ può essere dichiarato nello scope di un'interfaccia, protocollo o categoria Objective-C.

Comunque, classi Objective-C potrebbero servire come parametri di template C++. Parametri dei template di C++ possono anche essere usati come riceventi o parametri (comunque non come selettori) in espressioni di messaggi Objective-C.

C++ Ambiguità Lessicali e Conflitti

Ci sono pochi identificatori che sono definiti nei files header Objective-C che ogni programma Objective-C deve includere. Questi identificatori sono id, Class, SEL, IMP, e BOOL.
In un metodo Objective-C, Il compilatore pre-dichiara gli identificatori self e super, in modo simile alla parola chiave this in C++. Comunque, diversamente dalla parola chiave this in C++, self e super sono context-sensitive (sensibili al contesto); potrebbero essere usati come identificatori ordinari fuori ai metodi Objective-C.

Nella lista dei parametri dei metodi dentro un protocollo, ci sono altre cinque parole chiave context-sensitive (oneway, in, out, inout, and bycopy). Queste non sono parole chiavi in altri contesti.

Dal punto di vista di un programmatore Objective-C, C++ aggiunge parecchie nuove parole chiavi. Puoi usare ancora le parole chiavi C++ come parte di un selettore Objective-C, così l'impatto non è troppo severo, ma non puoi usarle per nominare classi Objective-C o variabili di istanza. Ad esempio, anche se class è una parola chiave C++, puoi ancora usare il metodo class: di NSObject.
[foo class]; // OK
Comunque, dato che è una parola chiave, non puoi usare class come il nome di una variabile:
NSObject *class; // Error
In Objective-C, i nomi per le classi e le categorie vivono in namespaces diversi. Che è, entrambi @interface foo e @interface(foo) possono esistere nello stesso codice sorgente. In Objective-C++, puoi anche avere una categoria i cui nomi combaciano con una classe o struttura C++.
Gli specificatori di protocollo e template usano la stessa sintassi per scopi diversi:
id foo;

TemplateType bar;

Per evitare quest'ambiguità, il compilatore non permette che id venga usato come nome di template.

Infine, c'è un'ambiguità lessicale in C++ quando un'etichetta è seguita da un'espressione che menziona un nome globale, come in:
label: ::global_name = 3;
Lo spazio dopo i primi due punti è richiesto. Objective-C++ aggiunge un caso simile, il quale richiede anch'esso uno spazio:
receiver selector: ::global_c++_name;

Limitazioni

Objective-C++ non aggiunge caratteristiche di C++ alle classi Objective-C, né aggiunge caratteristiche Objective-C a classi C++. Ad esempio, non puoi usare la sintassi Objective-C per chiamare un oggetto C++, non puoi aggiungere costruttori o distruttori per un oggetto Objective-C, e non puoi usare le parole chiave this e self intercambiabilmente. Le gerarchie di classi sono separate; una classe C++ non può ereditare da una classe Objective-C, e una classe Objective-C non può ereditare da una classe C++. Inoltre la gestione delle eccezioni multi-language non è supportata. Cioè, un'eccezione lanciata in codice Objective-C non può essere catturata nel codice C++, e un'eccezione lanciata nel codice C++ non può essere catturata nel codice Objective-C. Per più informazioni sulle eccezioni in Objective-C, consultate "Gestione delle Eccezioni".


Nessun commento:

Posta un commento

Related Posts with Thumbnails