Wie initialisiere ich eine const-Membervariable in einer Klasse?

105
#include <iostream>

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

  T1()
  {

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

Wenn ich versuche, die Variable const member tmit 100 zu initialisieren, erhalte ich jedoch den folgenden Fehler:

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

Wie kann ich einen constWert initialisieren ?

Chaitanya
quelle
8
Mit C ++ 11 ist dies möglich. Überprüfen Sie diesen Link stackoverflow.com/questions/13662441/…
Kapil

Antworten:

122

Die constVariable gibt an, ob eine Variable geändert werden kann oder nicht. Der zugewiesene konstante Wert wird jedes Mal verwendet, wenn auf die Variable verwiesen wird. Der zugewiesene Wert kann während der Programmausführung nicht geändert werden.

Die Erklärung von Bjarne Stroustrup fasst es kurz zusammen:

Eine Klasse wird normalerweise in einer Header-Datei deklariert, und eine Header-Datei ist normalerweise in vielen Übersetzungseinheiten enthalten. Um jedoch komplizierte Linkerregeln zu vermeiden, erfordert C ++, dass jedes Objekt eine eindeutige Definition hat. Diese Regel würde verletzt, wenn C ++ die Definition von Entitäten in der Klasse zulässt, die als Objekte im Speicher gespeichert werden müssen.

Eine constVariable muss innerhalb der Klasse deklariert werden, kann jedoch nicht darin definiert werden. Wir müssen die const-Variable außerhalb der Klasse definieren.

T1() : t( 100 ){}

Hier erfolgt die Zuweisung t = 100in der Initialisierungsliste, viel bevor die Klasseninitialisierung erfolgt.

Dinkar Thakur
quelle
3
Können Sie die letzte Aussage, die Here the i = 10 assignment in initializer list happens much before the class initilizaiton occurs.ich nicht verstehe, etwas näher erläutern ? Und im Grunde ist diese Art, Definitionen innerhalb der Klasse zuzulassen, compilerspezifisch, oder?
Chaitanya
3
Was ist i = 10 Zuordnung?
Daniel Daranas
Ich habe Konstanten in meiner Klasse, die ich auf die oben beschriebene Weise initialisiere. Wenn ich jedoch versuche, ein Objekt dieser Klasse zu erstellen, wird operator = function not foundin VC ++ ein Fehler angezeigt. Was kann das Problem sein?
Rohit Shinde
4
Wenn Sie die genauen Wörter einer Person ohne Zuschreibung verwenden, spricht man von Plagiaten. Bitte verwenden Sie die richtige Zuordnung - siehe stroustrup.com/bs_faq2.html#in-class und stackoverflow.com/questions/13662441/…
Tanaya
Ja, ich verstehe den Code in der Antwort auch überhaupt nicht - was zum Teufel ist das? Kann es in die Implementierung einer CPP-Datei eingefügt werden?
Tomáš Zato - Wiedereinsetzung Monica
50

Nun, du könntest es schaffen static:

static const int t = 100;

oder Sie könnten einen Mitgliedsinitialisierer verwenden:

T1() : t(100)
{
    // Other constructor stuff here
}
Fred Larson
quelle
2
Für seine Verwendung (und / oder Absichten) wäre es viel besser, es statisch zu machen.
Mark Garcia
@FredLarson Ist es so, als ob einige g ++ - Versionen diese Art von Initialisierungen nicht zulassen? oder ist es überhaupt nicht erlaubt?
Chaitanya
3
@Chaitanya: C ++ 11 Nicht statische Elementinitialisierer werden ab gcc 4.7 implementiert.
Jesse Good
@ MarkGarcia warum viel besser? es könnte auf Anforderung sein, wenn const membervon den Funktionen / Objekten aus zugänglich sein sollte, warum dann statisch?
Asif Mushtaq
Obwohl es normalerweise irreführend ist, Anfängern der statischen Aufladung ein Beispiel zu geben. Weil sie möglicherweise nicht wissen, dass es nur eine für alle Instanzen (Objekte) dieser Klasse ist.
Muhamed Cicak
30

Es gibt verschiedene Möglichkeiten, die const-Mitglieder innerhalb der Klasse zu initialisieren.

Die Definition des const-Elements im Allgemeinen erfordert auch die Initialisierung der Variablen.

1) Wenn Sie innerhalb der Klasse die Konstante initialisieren möchten, sieht die Syntax folgendermaßen aus

static const int a = 10; //at declaration

2) Der zweite Weg kann sein

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

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

3) Wenn Sie bei der Deklaration nicht initialisieren möchten, besteht die andere Möglichkeit darin, die Variable über den Konstruktor in der Initialisierungsliste (nicht im Hauptteil des Konstruktors) zu initialisieren. Es muss so sein

class A
{
  const int b;
  A(int c) : b(c) {} //const member initialized in initialization list
};
ravs2627
quelle
8
Ich denke, diese Antwort muss geklärt werden. Die Verwendung des statischen Schlüsselworts für ein Klassenmitglied fügt keine willkürliche Syntax hinzu, um den Compiler glücklich zu machen. Dies bedeutet, dass für alle Instanzen des Objekts, ob konstant oder nicht, eine einzige Kopie der Variablen vorhanden ist. Es ist eine Designentscheidung, die sorgfältig abgewogen werden muss. In der Folge könnte der Programmierer entscheiden, dass dieses konstante Klassenmitglied immer noch mit verschiedenen Objekten variieren kann, obwohl es für die Lebensdauer eines bestimmten Objekts konstant bleibt.
Opetrenko
Einverstanden. Wenn wir statisch verwenden, wird nur eine Kopie davon für alle Objekte erstellt. Wie Sie bereits erwähnt haben, ist dies eine Designauswahl. Bei Einzelkopie sollte für alle Objekte 1 und 2 funktionieren. Im Falle einer individuellen Kopie für jedes Objekt würde 3 funktionieren
ravs2627
Diese Antwort schlägt eine einfache Syntaxänderung ohne Konsequenzen vor - eine statische Änderung dagegen nicht.
Isaac Woods
Was ist, wenn Sie Double oder Float verwenden müssen? Ist dies ein Teil des C ++ 11-Standards?
Serup
14

Wenn Sie das constDatenelement in der Klasse nicht statisch machen möchten , können Sie das constDatenelement mithilfe des Konstruktors der Klasse initialisieren . Beispielsweise:

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

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

Wenn die constKlasse mehrere Datenelemente enthält, können Sie die Elemente mithilfe der folgenden Syntax initialisieren:

Example::Example(int n, int z):x(n),someOtherConstVariable(z){}
GANESH BK
quelle
3
Ich denke, dies liefert eine bessere Antwort als die, die akzeptiert wurde ...
Ian
1
Vielen Dank für die kristallklaren Beispiele und die Variante, die eine Vielzahl zeigt! Beseitigt Mehrdeutigkeiten und zusätzliche Recherchen / Scrollen seitens des Lesers!
klares Licht
13
  1. Sie können Ihren Compiler aktualisieren, um C ++ 11 zu unterstützen, und Ihr Code würde perfekt funktionieren.

  2. Verwenden Sie die Initialisierungsliste im Konstruktor.

    T1() : t( 100 )
    {
    }
borisbn
quelle
6

Eine andere Lösung ist

class T1
{
    enum
    {
        t = 100
    };

    public:
    T1();
};

T wird also auf 100 initialisiert und kann nicht geändert werden und ist privat.

Moschus
quelle
3

Wenn ein Mitglied ein Array ist, ist es etwas komplexer als das 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};

oder

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

class C {
  const std::vector<int> v;
public:
  C():v(a, a+N) {}
};
Viet Anh Do.
quelle
2

Ein anderer möglicher Weg sind Namespaces:

#include <iostream>

namespace mySpace {
   static const int T = 100; 
}

using namespace std;

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

Der Nachteil ist, dass auch andere Klassen die Konstanten verwenden können, wenn sie die Header-Datei enthalten.

Baran
quelle
1

Dies ist der richtige Weg. Sie können diesen Code ausprobieren.

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

Wenn Sie verwenden C++10 Compiler or below, können Sie das Cons-Mitglied zum Zeitpunkt der Deklaration nicht initialisieren. Hier muss also ein Konstruktor erstellt werden, um das const-Datenelement zu initialisieren. Es ist auch erforderlich, die Initialisiererliste zu verwenden, um T1():t(100)sofort Speicher zu erhalten.

Spieler Aziz
quelle
0

Sie können hinzufügen static, um die Initialisierung dieser Klassenmitgliedsvariablen zu ermöglichen.

static const int i = 100;

Dies ist jedoch nicht immer eine gute Vorgehensweise für die Verwendung innerhalb der Klassendeklaration, da alle von dieser Klasse instanziierten Objekte dieselbe statische Variable verwenden, die im internen Speicher außerhalb des Bereichsspeichers instanziierter Objekte gespeichert ist.

dhokar.w
quelle