Come inizializzare la variabile membro const in una classe?


105
#include <iostream>

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

  T1()
  {

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

Quando cerco di inizializzare la variabile membro const tcon 100. Ma mi dà il seguente errore:

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

Come posso inizializzare un constvalore?


8
con c ++ 11 questo è possibile controlla questo link stackoverflow.com/questions/13662441/…
Kapil

Risposte:


123

La constvariabile specifica se una variabile è modificabile o meno. Il valore della costante assegnato verrà utilizzato ogni volta che si fa riferimento alla variabile. Il valore assegnato non può essere modificato durante l'esecuzione del programma.

La spiegazione di Bjarne Stroustrup lo riassume brevemente:

Una classe è tipicamente dichiarata in un file di intestazione e un file di intestazione è tipicamente incluso in molte unità di traduzione. Tuttavia, per evitare complicate regole del linker, C ++ richiede che ogni oggetto abbia una definizione univoca. Questa regola sarebbe infranta se C ++ consentisse la definizione in classe di entità che dovevano essere archiviate in memoria come oggetti.

Una constvariabile deve essere dichiarata all'interno della classe, ma non può essere definita in essa. Dobbiamo definire la variabile const al di fuori della classe.

T1() : t( 100 ){}

Qui l'assegnazione t = 100avviene nell'elenco degli inizializzatori, molto prima che avvenga l'inizializzazione della classe.


3
Puoi essere un po 'elaborato sull'ultima affermazione Here the i = 10 assignment in initializer list happens much before the class initilizaiton occurs.che non ho capito. E fondamentalmente quel tipo di definizioni che consentono all'interno della classe è specifico del compilatore, giusto?
Chaitanya

3
Cosa i = 10 assegnazione?
Daniel Daranas

Ho delle costanti nella mia classe che inizializzo nel modo sopra. Tuttavia, quando provo a creare un oggetto di quella classe, mi dà un errore dicendo che operator = function not foundin VC ++. Quale può essere il problema?
Rohit Shinde

4
Quando usi le parole esatte di qualcuno senza attribuzione, si parla di plagio. Si prega di utilizzare la corretta attribuzione - vedi stroustrup.com/bs_faq2.html#in-class e stackoverflow.com/questions/13662441/...
Tanaya

Sì, anche io non capisco del tutto il codice nella risposta - che diavolo è quello? Può essere inserito nell'implementazione del file cpp?
Tomáš Zato - Ripristina Monica il

50

Bene, potresti farlo static:

static const int t = 100;

oppure puoi usare un inizializzatore di membri:

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

2
Per suo uso (e / o intenzioni), sarebbe molto meglio renderlo statico.
Mark Garcia

@FredLarson È come se alcune versioni di g ++ non consentissero questo tipo di inizializzazioni? o non è affatto permesso?
Chaitanya

3
@ Chaitanya: C ++ 11 Gli inizializzatori di membri non statici sono implementati da gcc 4.7.
Jesse Good

@MarkGarcia perché molto meglio? potrebbe essere su richiesta se const memberdovrebbe essere accessibile dalle funzioni / oggetti allora perché statico?
Asif Mushtaq

Anche se di solito è fuorviante dare un esempio ai principianti di statica. Perché, potrebbero non sapere che è solo uno per tutte le istanze (oggetti) di quella classe.
Muhamed Cicak

30

Esistono due modi per inizializzare i membri const all'interno della classe ..

La definizione di membro const in generale, richiede anche l'inizializzazione della variabile.

1) All'interno della classe, se vuoi inizializzare il const la sintassi è così

static const int a = 10; //at declaration

2) Il secondo modo può essere

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

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

3) Bene, se non si desidera inizializzare alla dichiarazione, l'altro modo è tramite il costruttore, la variabile deve essere inizializzata nell'elenco di inizializzazione (non nel corpo del costruttore). Deve essere così

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

8
Penso che questa risposta abbia bisogno di chiarimenti. L'uso della parola chiave statica per un membro della classe non aggiunge una sintassi arbitraria per rendere felice il compilatore. Significa che esiste un'unica copia della variabile per tutte le istanze dell'oggetto, costante o meno. È una scelta progettuale che deve essere considerata con attenzione. Lungo la linea il programmatore potrebbe decidere che questo membro della classe costante potrebbe ancora variare con oggetti diversi, nonostante rimanga costante per la durata di un dato oggetto.
opetrenko

D'accordo .. Quando usiamo statico, ne crea solo una copia per tutti gli oggetti .. Come hai detto è una scelta di design. In caso di copia singola per tutti gli oggetti 1 e 2 dovrebbe funzionare. In caso di copia individuale per ogni oggetto, 3 funzionerebbe
ravs2627

Questa risposta suggerisce un semplice cambiamento di sintassi senza conseguenze, mentre cambiarlo in modo statico non lo è.
Isaac Woods,

cosa succede se hai bisogno di usare double o float - fa parte dello standard C ++ 11?
serup

14

Se non si desidera rendere conststatico il membro dati nella classe, è possibile inizializzare il constmembro dati utilizzando il costruttore della classe. Per esempio:

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

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

se constnella classe sono presenti più membri dati, è possibile utilizzare la seguente sintassi per inizializzare i membri:

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

3
Penso che questo fornisca una risposta migliore di quella accettata ...
Ian

1
Grazie per gli esempi cristallini e la variante che mostra una pluralità! Eliminata ambiguità e ricerca / scorrimento extra da parte del lettore!
clearlight

13
  1. Puoi aggiornare il tuo compilatore per supportare C ++ 11 e il tuo codice funzionerà perfettamente.

  2. Usa l'elenco di inizializzazione nel costruttore.

    T1() : t( 100 )
    {
    }

6

Un'altra soluzione è

class T1
{
    enum
    {
        t = 100
    };

    public:
    T1();
};

Quindi t è inizializzato a 100 e non può essere modificato ed è privato.


3

Se un membro è un array, sarà un po 'complesso rispetto al normale:

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};

o

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

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

2

Un altro modo possibile sono gli spazi dei nomi:

#include <iostream>

namespace mySpace {
   static const int T = 100; 
}

using namespace std;

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

Lo svantaggio è che anche altre classi possono utilizzare le costanti se includono il file di intestazione.


1

Questo è il modo giusto per farlo. Puoi provare questo codice.

#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;
}

se stai usando, C++10 Compiler or belownon puoi inizializzare il membro contro al momento della dichiarazione. Quindi qui è necessario creare un costruttore per inizializzare il membro dati const. È inoltre necessario utilizzare l'elenco degli inizializzatori T1():t(100)per ottenere memoria all'istante.


0

è possibile aggiungere staticper rendere possibile l'inizializzazione di questa variabile membro di classe.

static const int i = 100;

Tuttavia, non è sempre una buona pratica usare la dichiarazione di classe interna, perché tutti gli oggetti istanziati da quella classe condivideranno la stessa variabile statica che è archiviata nella memoria interna al di fuori della memoria dell'ambito degli oggetti istanziati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.