Java'nın finaline karşı C ++ 's const


Yanıtlar:


195

C ++ işaretlemesinde üye işlevi const, constörneklerde çağrılabileceği anlamına gelir . Java'nın buna eşdeğer bir değeri yoktur. Örneğin:

class Foo {
public:
   void bar();
   void foo() const;
};

void test(const Foo& i) {
   i.foo(); //fine
   i.bar(); //error
}

Değerler, bir kez, daha sonra yalnızca Java ile atanabilir, örneğin:

public class Foo {
   void bar() {
     final int a;
     a = 10;
   }
}

Java'da yasaldır, ancak C ++ değil:

public class Foo {
   void bar() {
     final int a;
     a = 10;
     a = 11; // Not legal, even in Java: a has already been assigned a value.
   }
}

Hem Java hem de C ++ üye değişkenlerinde sırasıyla final/ olabilir const. Bunlara, sınıfın bir örneğinin oluşturulmasını tamamlayana kadar bir değer verilmelidir.

Java'da yapıcı bitmeden önce ayarlanmalıdırlar, bu iki yoldan biriyle gerçekleştirilebilir:

public class Foo {
   private final int a;
   private final int b = 11;
   public Foo() {
      a = 10;
   }
}

C ++ 'da constüyelere bir değer vermek için başlatma listelerini kullanmanız gerekir :

class Foo {
   const int a;
public:
   Foo() : a(10) {
      // Assignment here with = would not be legal
   }
};

Java'da final, işleri geçersiz kılınamaz olarak işaretlemek için kullanılabilir. C ++ (C ++ öncesi 11) bunu yapmaz. Örneğin:

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

Ancak C ++ ile:

class Bar {
public:
   virtual void foo() const {
   }
};

class Error: public Bar {
public:
   // Fine in C++
   virtual void foo() const {
   }
};

üye bir işlevi işaretlemenin anlambilimi constfarklı olduğu için bu iyidir . (Ayrıca üye işlevlerinden yalnızca birine sahip olarak aşırı yükleyebilirsinizconst . (Ayrıca, C ++ 11'in üye işlevlerinin son olarak işaretlenmesine izin verdiğini unutmayın, C ++ 11 güncelleme bölümüne bakın)


C ++ 11 güncellemesi:

C ++ 11 aslında hem sınıfları hem de üye işlevlerini final, Java'daki aynı özelliğe, örneğin Java'daki aynı semantikle işaretlemenize izin verir :

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

Artık C ++ 11 ile tam olarak şu şekilde yazılabilir:

class Bar {
public:
  virtual void foo() final;
};

class Error : public Bar {
public:
  virtual void foo() final;
};

Bu örneği G ++ 4.7'nin ön sürümüyle derlemem gerekiyordu. Bunun constbu durumda değiştirilmediğini , aksine artırdığını ve en yakın eşdeğer C ++ anahtar sözcüğüyle görülmeyen Java benzeri davranışı sağladığını unutmayın. Bir üye işlevinin her ikisinin de olmasını istiyorsanız finalve constbunu yapsaydınız:

class Bar {
public:
  virtual void foo() const final;
};

(Sırası constve finalburada gereklidir).

Önceden constüye işlevlerinin doğrudan eşdeğeri yoktu, ancak işlevleri virtualderleme zamanında bir hataya neden olmadan potansiyel bir seçenek olmazdı.

Aynı şekilde Java:

public final class Bar {
}

public class Error extends Bar {
}

C ++ 11'de olur:

class Bar final {
};

class Error : public Bar {
};

(Önceden privateyapıcılar muhtemelen C ++ ile bu kadar yakın olabilirdi)

İlginç bir şekilde, C ++ 11 öncesi kod ile geriye dönük uyumluluğu korumak için her zamanki gibi bir anahtar kelime final değildir . ( struct final;Neden bir anahtar kelime yapmanın kodu bozacağını görmek için önemsiz, yasal C ++ 98 örneğini alın )


3
Bu yöntemleri sanal yapmalısınız; aksi takdirde, gerçekten aynı şeyi yapmıyorsunuz
BlueRaja - Danny Pflughoeft

1
Son örneğinizde, sahip olduğunuz şey yasaldır, ancak bunun final int a; a = 10; a = 11;( finaldeğişken değiştirici olarak amaç olduğunu) belirtmek gerekir . Ayrıca, bir sınıfın son üyeleri yalnızca bildirim zamanında veya bir yapıcıda bir kez ayarlanabilir .
corsiKa

2
C ++ 0x finalbu tam amaç için üye işlevi dekoratör eklediğini unutmayın . VC ++ 2005, 2008 ve 2010, içeriğe dayalı anahtar kelime sealedyerine bunu zaten uyguladı final.
ildjarn

@ildjarn -Bunu bilmek ilginç ve henüz bilmediğim nispeten küçük bir C ++ 0x değişikliği! Muhtemelen bu C ++ 0x ile değiştiğini belirten metinde küçük bir yorum ekleyeceğim.
Flekso

1
Görünüşe göre insanlar hala sonuç olarak finalructor ile kod tabanlarında hala s / const / final / g yapıyorlar !
Flekso

30

Java'da son anahtar kelime dört şey için kullanılabilir:

  • mühürlemek için bir sınıfta veya yöntemde (alt sınıflara / geçersiz kılmaya izin verilmez)
  • üye değişkeninde bunun tam olarak bir kez ayarlanabileceğini bildirmek için (bahsettiğiniz şey budur)
  • tam olarak bir kez ayarlanabildiğinden emin olmak için bir yöntemde bildirilen bir değişkene
  • bir yöntem parametresinde, yöntem içinde değiştirilemeyeceğini bildirmek için

Önemli bir şey: Bir Java nihai üye değişkeni gerekir tam olarak bir kez ayarlanabilir! Örneğin, bir kurucuda, alan bildiriminde veya başlatıcıda. (Ancak bir yöntemde son üye değişkeni ayarlayamazsınız).

Üye değişkeni sonlandırmanın bir başka sonucu da, dişli bir ortamda çalışmanız durumunda önemli olan bellek modeli ile ilgilidir.


'Bellek modeli' demekle ne demek istiyorsun? Anlamıyorum.
Tony

1
@Tony: Java Dili Belirtimi, Bölüm 17.4. Bellek Modeli - docs.oracle.com/javase/specs/jls/se8/html/index.html - googles ilk hit
Ralph

27

Bir constnesne sadece constyöntemleri çağırabilir ve genellikle değişmez olarak kabul edilir.

const Person* person = myself;
person = otherPerson; //Valid... unless we declared it const Person* const!
person->setAge(20); //Invalid, assuming setAge isn't a const method (it shouldn't be)

Bir finalnesne yeni bir nesneye ayarlanamaz, ancak değişmez değildir - birisinin herhangi bir setyöntem çağırmasını engelleyen hiçbir şey yoktur .

final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!

Java'nın nesneleri değişmez ilan etmenin doğal bir yolu yoktur; sınıfı kendiniz değişmez olarak tasarlamanız gerekir.

Değişken ilkel bir tür olduğunda final/ constaynı şekilde çalışır.

const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages

3
Bu da harika bir cevap (buradaki diğerleri gibi). Ne yazık ki, sadece bir cevabı kabul edebilirim. :)
WinWin

1
Mükemmel cevap!
ADJ

13

Java finali, ilkel değer türlerindeki C ++ sabitine eşdeğerdir.

Java başvuru türlerinde, son anahtar kelime bir sabit işaretçiye eşdeğerdir ... yani

//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();

//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();

"son anahtar kelime bir sabit işaretçiye eşdeğerdir" iyi dedi
ADJ

8

Burada zaten bazı harika cevaplarınız var, ancak eklemeye değer gibi görünen bir nokta var: constC ++ 'da programın diğer bölümlerinin nesnelerin durumunu değiştirmesini önlemek için yaygın olarak kullanılır. Belirtildiği gibi, finaljava'da bunu yapamaz (ilkeller hariç) - sadece referansın farklı bir nesneye değiştirilmesini önler . Ancak a Collectionkullanıyorsanız, statik yöntemi kullanarak nesnelerinizdeki değişiklikleri önleyebilirsiniz

 Collection.unmodifiableCollection( myCollection ) 

Bu Collection, öğelere okuma erişimi sağlayan bir başvuru döndürür , ancak değişiklikler denenirse bir istisna atar constve C ++ ' da biraz benzer hale getirir.


8

Java finalsadece ilkel türler ve referanslar üzerinde çalışır, asla const anahtar sözcüğünün herhangi bir şey üzerinde çalıştığı nesne örneklerinde kendileri üzerinde çalışmaz.

Karşılaştırma const list<int> melist;ile final List<Integer> melist;ikincisi sadece yeni bir liste atayarak alıkoyar ederken, imkansız listeyi değiştirmek için ilk marka melist.


3

Belirli ve ince çok iş parçacıklı özelliklere sahip olmanın yanı sıra, beyan edilen değişkenlerin finalbildirimde başlatılması gerekmez!

ie Bu, Java için geçerlidir:

// declare the variable
final int foo;

{
    // do something...

    // and then initialize the variable
    foo = ...;
}

C ++ 'larla yazılırsa bu geçerli olmaz const.


2

Vikipedi göre :

  • C ++ 'da, bir const alanı yalnızca yeniden atanmaya karşı korunmakla kalmaz, aynı zamanda yalnızca const yöntemlerinin çağrılabileceği ve yalnızca diğer yöntemlerin const argümanı olarak iletilebileceği ek sınırlama vardır.
  • Statik olmayan iç sınıflar, kapalı ya da kapalı sınıfın herhangi bir alanına serbestçe erişebilir.

1
'Yeniden atanmış' kelimesi o sayfanın geçerli sürümünde görünmüyor ve 'erişim' ile kastettiğinize bağlı olarak yanlış veya alakasız olan ikinci noktanıza benzeyen hiçbir şey de yok. 'Statik olmayan iç' çift konuşmadır. Wikipedia, C ++ veya Java için normatif bir referans değildir.
Lorne Marquis

2

Ben constişaretçiler, yani sabit işaretçiler vs sabit nesnelere işaretçiler hakkında konuşurken C kabaca anlamı "kabaca" diyor tahmin ediyorum . Java'da "açık" işaretçiler finalolmadığından, bu sorunlar yoktur.


1

Anladığım şeyi bir switch / case ifadesi örneğiyle açıklayayım.

Her vaka ifadesindeki değerler, anahtar değeri ile aynı veri türünün derleme zamanı sabit değerleri olmalıdır.

aşağıdaki gibi bir şey (yerel örnek olarak yönteminizde veya sınıfınızda statik değişken olarak (o zaman statik ekleyin) veya bir örnek değişkeni bildirin.

final String color1 = "Red";

ve

static final String color2 = "Green";

switch (myColor) { // myColor is of data type String
    case color1:
    //do something here with Red
    break;
    case color2:
    //do something with Green
    break;
}

color1Bir yerel değişken değil, bir sınıf / örnek değişkeni ise bu kod derlenmeyecektir . Bu derleme olacak color1statik nihai (o zaman statik nihai değişken haline gelir) olarak tanımlanır.

Derlenmediğinde, aşağıdaki hatayı alırsınız

error: constant string expression required

-7

"const" anahtar kelimesi, değişkeninizin ROM'a (Mikroişlemci ile) kaydedildiği anlamına gelir. bilgisayarda, değişkeniniz Montaj kodu için RAM alanına kaydedilir (salt okunur RAM). değişkeninizin yazılabilir RAM'de olmadığı anlamına gelir: statik bellek, yığın bellek ve yığın bellek.

"final" anahtar kelimesi, değişkeninizin yazılabilir RAM'e kaydedildiği anlamına gelir, ancak derleyicinizin değişkeninizin yalnızca bir kez değiştiğini fark edersiniz.

//in java language you can use:
static final int i =10;
i =11; //error is showed here by compiler

//the same in C++ the same as follows
int i =10;
const int &iFinal = i;

iFinal = 11; //error is showed here by compiler the same as above

"Const" performansının kötü olduğunu düşünüyorum, bu yüzden Java bunu kullanmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.