Nella marcatura C ++ una funzione membro const
significa che può essere chiamata su const
istanze. Java non ha un equivalente a questo. Per esempio:
class Foo {
public:
void bar();
void foo() const;
};
void test(const Foo& i) {
i.foo(); //fine
i.bar(); //error
}
I valori possono essere assegnati, una volta, successivamente solo in Java, ad esempio:
public class Foo {
void bar() {
final int a;
a = 10;
}
}
è legale in Java, ma non in C ++ mentre:
public class Foo {
void bar() {
final int a;
a = 10;
a = 11; // Not legal, even in Java: a has already been assigned a value.
}
}
In Java e C ++ le variabili membro possono essere final
/ const
rispettivamente. A questi deve essere assegnato un valore al termine della costruzione di un'istanza della classe.
In Java devono essere impostati prima che il costruttore abbia terminato, ciò può essere ottenuto in due modi:
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
In C ++ dovrai usare gli elenchi di inizializzazione per dare const
un valore ai membri:
class Foo {
const int a;
public:
Foo() : a(10) {
// Assignment here with = would not be legal
}
};
In Java final può essere utilizzato per contrassegnare le cose come non sostituibili. C ++ (pre-C ++ 11) non lo fa. Per esempio:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Ma in C ++:
class Bar {
public:
virtual void foo() const {
}
};
class Error: public Bar {
public:
// Fine in C++
virtual void foo() const {
}
};
questo va bene, perché la semantica della marcatura di una funzione membro const
è diversa. (Potresti anche sovraccaricare avendo solo const
una delle funzioni membro. (Notare anche che C ++ 11 consente alle funzioni membro di essere contrassegnate come finali, vedere la sezione di aggiornamento di C ++ 11)
Aggiornamento C ++ 11:
C ++ 11 infatti consente di contrassegnare sia le classi che le funzioni membro come final
, con semantica identica alla stessa funzionalità in Java, ad esempio in Java:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Ora può essere scritto esattamente in C ++ 11 come:
class Bar {
public:
virtual void foo() final;
};
class Error : public Bar {
public:
virtual void foo() final;
};
Ho dovuto compilare questo esempio con una pre-release di G ++ 4.7. Si noti che questo non sostituisce const
in questo caso, ma piuttosto lo aumenta, fornendo il comportamento simile a Java che non è stato visto con la parola chiave C ++ equivalente più vicina. Quindi, se si desidera che una funzione membro sia entrambe final
e const
si farebbe:
class Bar {
public:
virtual void foo() const final;
};
(L'ordine di const
efinal
qui è obbligatorio).
In precedenza non esisteva un equivalente diretto delle const
funzioni membro, sebbene le funzioni non fosserovirtual
sarebbe una potenziale opzione sebbene senza causare un errore in fase di compilazione.
Allo stesso modo Java:
public final class Bar {
}
public class Error extends Bar {
}
diventa in C ++ 11:
class Bar final {
};
class Error : public Bar {
};
(In precedenza private
costruttori erano probabilmente i più vicini a questo in C ++)
È interessante notare che per mantenere la retrocompatibilità con il codice pre-C ++ 11 final
non è una parola chiave nel solito modo. (Prendi l'esempio banale e legale di C ++ 98 struct final;
per capire perché trasformarlo in una parola chiave romperebbe il codice)