Bir sınıfta const üye değişkeni nasıl başlatılır?


105
#include <iostream>

using namespace std;
class T1
{
  const int t = 100;
  public:

  T1()
  {

    cout << "T1 constructor: " << t << endl;
  }
};

Const üye değişkenini t100 ile başlatmaya çalıştığımda. Ama bana şu hatayı veriyor:

test.cpp:21: error: ISO C++ forbids initialization of member t
test.cpp:21: error: making t static

Bir constdeğeri nasıl başlatabilirim ?


8
c ++ 11 ile bu mümkündür. stackoverflow.com/questions/13662441/…
Kapil

Yanıtlar:


123

constDeğişken belirtir değişken değiştirilebilir olup olmadığını. Atanan sabit değer, değişkene her başvurulduğunda kullanılacaktır. Atanan değer, program yürütülürken değiştirilemez.

Bjarne Stroustrup'un açıklaması bunu kısaca özetliyor:

Bir sınıf genellikle bir başlık dosyasında bildirilir ve bir başlık dosyası genellikle birçok çeviri birimine dahil edilir. Ancak, karmaşık bağlayıcı kurallarından kaçınmak için, C ++ her nesnenin benzersiz bir tanıma sahip olmasını gerektirir. C ++, bellekte nesneler olarak depolanması gereken varlıkların sınıf içi tanımına izin verirse, bu kural bozulur.

constSınıf içinde bir değişken bildirilmelidir, ancak içinde tanımlanamaz. Const değişkenini sınıfın dışında tanımlamamız gerekiyor.

T1() : t( 100 ){}

Burada atama t = 100, sınıf başlatma gerçekleşmeden çok önce başlatıcı listesinde gerçekleşir.


3
Bunu Here the i = 10 assignment in initializer list happens much before the class initilizaiton occurs.anlayamadığım son cümle hakkında biraz detay verebilir misin? Ve temelde bu tür sınıf içinde tanımlara izin vermek derleyiciye özgü değil mi?
Chaitanya

3
İ = 10 atama nedir?
Daniel Daranas

Sınıfımda yukarıdaki şekilde başlattığım sabitler var. Ancak, o sınıfın bir nesnesini oluşturmaya çalıştığımda, bunu operator = function not foundVC ++ 'da söyleyerek bana bir hata veriyor . Sorun ne olabilir?
Rohit Shinde

4
Birinin tam sözlerini atıfta bulunmadan kullandığınızda buna intihal denir. Lütfen doğru atıf kullanın - bkz. Stroustrup.com/bs_faq2.html#in-class ve stackoverflow.com/questions/13662441/…
Tanaya

Evet, yanıttaki kodu da tamamen anlamıyorum - bu da neyin nesi? Cpp dosya uygulamasına yerleştirilebilir mi?
Tomáš Zato - Monica'yı

50

Peki, yapabilirsin static:

static const int t = 100;

veya bir üye başlatıcı kullanabilirsiniz:

T1() : t(100)
{
    // Other constructor stuff here
}

2
Onun kullanımı (ve / veya niyetleri) için, onu statik yapmak çok daha iyi olacaktır.
Mark Garcia

@FredLarson Bazı g ++ sürümleri bu tür başlatmalara izin vermiyor gibi mi? ya da hiç izin verilmiyor mu?
Chaitanya

3
@Chaitanya: C ++ 11 Statik olmayan üye başlatıcılar gcc 4.7'den gerçeklenmiştir.
Jesse Good

@MarkGarcia neden daha iyi? eğer gereksinimi üzerinde olabilir const memberişlevlerden erişilebilir olmalıdır neden statik sonra / nesnelerin?
Asif Mushtaq

Statik yeni başlayanlara bir örnek vermek genellikle yanıltıcıdır. Çünkü, o sınıfın tüm örnekleri (nesneleri) için bunun yalnızca bir tane olduğunu bilmeyebilirler.
Muhamed Cicak

30

Const üyelerini sınıfın içinde başlatmanın birkaç yolu vardır ..

Genel olarak const üyesinin tanımı, değişkenin başlatılmasına da ihtiyaç duyar ..

1) Sınıfın içinde, const'ı başlatmak istiyorsanız sözdizimi şu şekildedir:

static const int a = 10; //at declaration

2) İkinci yol olabilir

class A
{
  static const int a; //declaration
};

const int A::a = 10; //defining the static member outside the class

3) Açıklamada başlatmak istemiyorsanız, diğer yol kurucu aracılığıyla yapmaktır, değişkenin ilklendirme listesinde başlatılması gerekir (kurucunun gövdesinde değil). Böyle olmalı

class A
{
  const int b;
  A(int c) : b(c) {} //const member initialized in initialization list
};

8
Sanırım bu cevabın açıklığa kavuşturulması gerekiyor. Bir sınıf üyesi için statik anahtar sözcüğün kullanılması, derleyiciyi mutlu etmek için bazı rasgele sözdizimleri eklemiyor. Sabit olsun ya da olmasın, nesnenin tüm örnekleri için değişkenin tek bir kopyası olduğu anlamına gelir. Dikkatlice düşünülmesi gereken bir tasarım seçimidir. Çizginin aşağısında programcı, belirli bir nesnenin ömrü boyunca sabit kalmasına rağmen, bu sabit sınıf üyesinin hala farklı nesnelerle değişebileceğine karar verebilir.
opetrenko

Anlaştık .. Statik kullandığımızda, tüm nesneler için sadece bir kopyasını oluşturur .. Dediğiniz gibi bir tasarım seçeneği. Tüm nesneler için tek kopya olması durumunda 1 ve 2 çalışmalıdır. Her nesne için ayrı kopya olması durumunda, 3 işe
yarar

Bu cevap, sonuçları olmayan basit bir sözdizimi değişikliğini önerir - oysa onu statik olarak değiştirmek değildir.
Isaac Woods

ya double veya float kullanmanız gerekirse - bu C ++ 11 standardının bir parçası mı?
serup

14

constVeri üyesini sınıfta statik yapmak istemiyorsanız const, sınıfın yapıcısını kullanarak veri üyesini başlatabilirsiniz . Örneğin:

class Example{
      const int x;
    public:
      Example(int n);
};

Example::Example(int n):x(n){
}

constsınıfta birden fazla veri üyesi varsa, üyeleri başlatmak için aşağıdaki sözdizimini kullanabilirsiniz:

Example::Example(int n, int z):x(n),someOtherConstVariable(z){}

3
Sanırım bu, kabul edilenden daha iyi bir cevap
Ian

1
Kristal netliğinde örnekler ve çoğulluğu gösteren varyant için teşekkür ederiz! Okuyucu tarafında belirsizlik ve ekstra araştırma / kaydırma ortadan kaldırıldı!
2018

13
  1. Derleyicinizi C ++ 11'i destekleyecek şekilde yükseltebilirsiniz ve kodunuz mükemmel çalışır.

  2. Yapıcıda başlatma listesini kullanın.

    T1() : t( 100 )
    {
    }
    

6

Başka bir çözüm ise

class T1
{
    enum
    {
        t = 100
    };

    public:
    T1();
};

Yani t 100 olarak başlatılır ve değiştirilemez ve özeldir.


3

Bir üye bir Dizi ise, normalden biraz daha karmaşık olacaktır:

class C
{
    static const int ARRAY[10];
 public:
    C() {}
};
const unsigned int C::ARRAY[10] = {0,1,2,3,4,5,6,7,8,9};

veya

int* a = new int[N];
// fill a

class C {
  const std::vector<int> v;
public:
  C():v(a, a+N) {}
};

2

Başka bir olası yol ad alanlarıdır:

#include <iostream>

namespace mySpace {
   static const int T = 100; 
}

using namespace std;

class T1
{
   public:
   T1()
   {
       cout << "T1 constructor: " << mySpace::T << endl;
   }
};

Dezavantajı, başlık dosyasını içeriyorlarsa diğer sınıfların da sabitleri kullanabilmesidir.


1

Bunu yapmanın doğru yolu budur. Bu kodu deneyebilirsiniz.

#include <iostream>

using namespace std;

class T1 {
    const int t;

    public:
        T1():t(100) {
            cout << "T1 constructor: " << t << endl;
        }
};

int main() {
    T1 obj;
    return 0;
}

kullanıyorsanız C++10 Compiler or below, bildirim anında eksper üyesini başlatamazsınız. Yani burada const veri üyesini başlatmak için bir kurucu yapmak gerekir. Aynı zamanda T1():t(100)hafızayı anında almak için başlatıcı listesini kullanmak gerekir .


0

staticbu sınıf üyesi değişkeninin başlatılmasını mümkün kılmak için ekleyebilirsiniz .

static const int i = 100;

Bununla birlikte, bu sınıf bildiriminde kullanmak için her zaman iyi bir uygulama değildir, çünkü bu sınıftan başlatılan tüm nesneler, başlatılan nesnelerin kapsam belleğinin dışında dahili bellekte depolanan aynı statik değişkeni paylaşacaktır.

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.