W C ++ oznaczenie funkcji const
składowej oznacza, że może być wywoływana w const
instancjach. Java nie ma odpowiednika tego. Na przykład:
class Foo {
public:
void bar();
void foo() const;
};
void test(const Foo& i) {
i.foo(); //fine
i.bar(); //error
}
Wartości można przypisać jednorazowo, później tylko w Javie, np .:
public class Foo {
void bar() {
final int a;
a = 10;
}
}
jest legalne w Javie, ale nie w C ++, podczas gdy:
public class Foo {
void bar() {
final int a;
a = 10;
a = 11; // Not legal, even in Java: a has already been assigned a value.
}
}
Zarówno w Javie, jak i C ++ zmiennymi składowymi mogą być odpowiednio final
/ const
. Muszą one otrzymać wartość do czasu zakończenia tworzenia instancji klasy.
W Javie muszą być ustawione przed zakończeniem pracy konstruktora, można to osiągnąć na dwa sposoby:
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
W C ++ będziesz musiał użyć list inicjalizacyjnych, aby nadać const
członkom wartość:
class Foo {
const int a;
public:
Foo() : a(10) {
// Assignment here with = would not be legal
}
};
W Java final może być używany do oznaczania rzeczy jako niepodlegających zastąpieniu. C ++ (przed C ++ 11) tego nie robi. Na przykład:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Ale w C ++:
class Bar {
public:
virtual void foo() const {
}
};
class Error: public Bar {
public:
// Fine in C++
virtual void foo() const {
}
};
to jest w porządku, ponieważ semantyka oznaczania funkcji składowej const
jest inna. (Możesz również przeciążać , mając tylko const
na jednej z funkcji składowych. (Zwróć również uwagę, że C ++ 11 umożliwia oznaczanie funkcji składowych jako ostateczne, zobacz sekcję Aktualizacja C ++ 11)
Aktualizacja C ++ 11:
C ++ 11 w rzeczywistości pozwala na oznaczanie zarówno klas, jak i funkcji składowych jako final
, z identyczną semantyką dla tej samej funkcji w Javie, na przykład w Javie:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Można teraz dokładnie zapisać w C ++ 11 jako:
class Bar {
public:
virtual void foo() final;
};
class Error : public Bar {
public:
virtual void foo() final;
};
Musiałem skompilować ten przykład z wersją wstępną G ++ 4.7. Zauważ, że nie zastępuje const
to w tym przypadku, ale raczej go rozszerza, zapewniając zachowanie podobne do Java, którego nie widziano z najbliższym odpowiednikiem słowa kluczowego C ++. Więc jeśli chcesz, aby funkcja członkowska była jednocześnie final
i const
zrobiłbyś:
class Bar {
public:
virtual void foo() const final;
};
(Kolejność const
i final
tutaj jest wymagana).
Wcześniej nie było bezpośredniego odpowiednika const
funkcji składowych, chociaż uczynienie funkcji innymi niż- virtual
byłoby potencjalną opcją, aczkolwiek bez powodowania błędu w czasie kompilacji.
Podobnie Java:
public final class Bar {
}
public class Error extends Bar {
}
staje się w C ++ 11:
class Bar final {
};
class Error : public Bar {
};
(Wcześniej private
konstruktory były prawdopodobnie najbliższe tego, co można było uzyskać w C ++)
Co ciekawe, w celu zachowania wstecznej kompatybilności z kodem sprzed wersji C ++ 11 w zwykły sposób final
nie jest słowem kluczowym. (Weź trywialny, legalny przykład C ++ 98, struct final;
aby zobaczyć, dlaczego uczynienie go słowem kluczowym spowodowałoby uszkodzenie kodu)