Frage

Ich habe die folgende Klasse in C ++:

class a {
    const int b[2];
    // other stuff follows

    // and here's the constructor
    a(void);
}

Die Frage ist, wie ich B in der Initialisierungsliste initialisieren kann, da ich es nicht im Körper der Funktion des Konstruktors initialisieren kann, da B ist, da B ist const?

Das funktioniert nicht:

a::a(void) : 
    b([2,3])
{
     // other initialization stuff
}

Bearbeiten: Der Fall tätig ist, wenn ich unterschiedliche Werte für haben kann b Für verschiedene Fälle, aber die Werte sind für die Lebensdauer der Instanz konstant.

War es hilfreich?

Lösung

Wie die anderen sagten, unterstützt ISO C ++ das nicht. Aber Sie können es verarbeiten. Verwenden Sie stattdessen einfach STD :: Vektor.

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

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

Andere Tipps

Mit C ++ 11 hat sich die Antwort auf diese Frage jetzt geändert und Sie können tatsächlich:

struct a {
    const int b[2];
    // other bits follow

    // and here's the constructor
    a();
};

a::a() :
    b{2,3}
{
     // other constructor work
}

int main() {
 a a;
}

Es ist im aktuellen Standard nicht möglich. Ich glaube Ein kurzer Blick auf C ++ 0x, Von Bjarne Stroustrup finden Sie weitere Informationen zu Initialisiererlisten und anderen schönen C ++ 0x -Funktionen).

std::vector verwendet den Haufen. Meine Güte, was für ein Abfall, das nur für einen Willen sein würde const Gesundheitsüberprüfung. Der Punkt von std::vector ist ein dynamisches Wachstum zur Laufzeit, keine alte Syntaxüberprüfung, die zum Zeitpunkt der Kompilierung durchgeführt werden sollte. Wenn Sie nicht wachsen möchten, erstellen Sie eine Klasse, um ein normales Array zu wickeln.

#include <stdio.h>


template <class Type, size_t MaxLength>
class ConstFixedSizeArrayFiller {
private:
    size_t length;

public:
    ConstFixedSizeArrayFiller() : length(0) {
    }

    virtual ~ConstFixedSizeArrayFiller() {
    }

    virtual void Fill(Type *array) = 0;

protected:
    void add_element(Type *array, const Type & element)
    {
        if(length >= MaxLength) {
            // todo: throw more appropriate out-of-bounds exception
            throw 0;
        }
        array[length] = element;
        length++;
    }
};


template <class Type, size_t Length>
class ConstFixedSizeArray {
private:
    Type array[Length];

public:
    explicit ConstFixedSizeArray(
        ConstFixedSizeArrayFiller<Type, Length> & filler
    ) {
        filler.Fill(array);
    }

    const Type *Array() const {
        return array;
    }

    size_t ArrayLength() const {
        return Length;
    }
};


class a {
private:
    class b_filler : public ConstFixedSizeArrayFiller<int, 2> {
    public:
        virtual ~b_filler() {
        }

        virtual void Fill(int *array) {
            add_element(array, 87);
            add_element(array, 96);
        }
    };

    const ConstFixedSizeArray<int, 2> b;

public:
    a(void) : b(b_filler()) {
    }

    void print_items() {
        size_t i;
        for(i = 0; i < b.ArrayLength(); i++)
        {
            printf("%d\n", b.Array()[i]);
        }
    }
};


int main()
{
    a x;
    x.print_items();
    return 0;
}

ConstFixedSizeArrayFiller und ConstFixedSizeArray sind wiederverwendbar.

Die erste ermöglicht die Überprüfung der Laufzeitgrenzen beim Initialisieren des Arrays (wie ein Vektor), der später werden kann const Nach dieser Initialisierung.

Die zweite ermöglicht es, das Array zuzuweisen Innerhalb Ein anderes Objekt, das sich auf dem Haufen oder einfach auf dem Stapel befinden kann, wenn das Objekt dort ist. Es gibt keine Zeitverschwendung, aus dem Haufen zuzuweisen. Es führt auch die Überprüfung der Kompilierzeitkontrolle im Array durch.

b_filler ist eine winzige private Klasse, um die Initialisierungswerte bereitzustellen. Die Größe des Arrays wird bei der Kompilierungszeit mit den Vorlagenargumenten überprüft, sodass keine Chance besteht, aus den Grenzen zu gehen.

Ich bin sicher, dass es exotischere Möglichkeiten gibt, dies zu ändern. Dies ist ein anfänglicher Stich. Ich denke, Sie können einen der Manko des Compiler mit Klassen so ziemlich wieder gut machen.

ISO Standard C ++ lässt Sie dies nicht tun. Wenn dies der Fall wäre, wäre die Syntax wahrscheinlich:

a::a(void) :
b({2,3})
{
    // other initialization stuff
}

Oder etwas in dieser Richtung. Aus Ihrer Frage klingt es tatsächlich nach dem, was Sie wollen, ein ständiges Mitglied (auch bekannt als statisches) Mitglied, das das Array ist. C ++ lässt Sie dies tun. Like SO:

#include <iostream>

class A 
{
public:
    A();
    static const int a[2];
};

const int A::a[2] = {0, 1};

A::A()
{
}

int main (int argc, char * const argv[]) 
{
    std::cout << "A::a => " << A::a[0] << ", " << A::a[1] << "\n";
    return 0;
}

Die Ausgabe ist:

A::a => 0, 1

Nun, da dies ein statisches Klassenmitglied ist, ist es für jede Instanz von Klasse A das gleiche, wenn dies nicht das ist, was Sie wollen, dh Sie möchten, dass jede Instanz von A unterschiedliche Elementwerte im Array A hat, dann machen Sie dann Sie Der Fehler, den Array Const zu machen, damit der Array zu beginnen. Sie sollten einfach das tun:

#include <iostream>

class A 
{
public:
    A();
    int a[2];
};

A::A()
{
    a[0] = 9; // or some calculation
    a[1] = 10; // or some calculation
}

int main (int argc, char * const argv[]) 
{
    A v;
    std::cout << "v.a => " << v.a[0] << ", " << v.a[1] << "\n";
    return 0;
}

Wo ich ein ständiges Array habe, wurde es immer als statisch gemacht. Wenn Sie dies akzeptieren können, sollte dieser Code kompilieren und ausgeführt werden.

#include <stdio.h>
#include <stdlib.h>

class a {
        static const int b[2];
public:
        a(void) {
                for(int i = 0; i < 2; i++) {
                        printf("b[%d] = [%d]\n", i, b[i]);
                }
        }
};

const int a::b[2] = { 4, 2 };

int main(int argc, char **argv)
{
        a foo;
        return 0;
}

Sie können das nicht aus der Initialisierungsliste tun.

Schau dir das an:

http://www.cprogramming.com/tutorial/initialization-list-c++.html

:)

Eine Lösung ohne den Haufen mit std::vector ist zu verwenden boost::array, obwohl Sie Array -Mitglieder nicht direkt im Konstruktor initialisieren können.

#include <boost/array.hpp>

const boost::array<int, 2> aa={ { 2, 3} };

class A {
    const boost::array<int, 2> b;
    A():b(aa){};
};

Wie wäre es mit einer Konstantarray über eine Accessor -Funktion? Es ist nicht statisch (wie Sie angefordert haben) und es ist weder STL noch eine andere Bibliothek erforderlich:

class a {
    int privateB[2];
public:
    a(int b0,b1) { privateB[0]=b0; privateB[1]=b1; }
    int b(const int idx) { return privateB[idx]; }
}

Weil a :: privatb privat ist, ist es außerhalb von A :: effektiv konstant, und Sie können ähnlich wie ein Array, z. B.

a aobj(2,3);    // initialize "constant array" b[]
n = aobj.b(1);  // read b[1] (write impossible from here)

Wenn Sie bereit sind, ein Klassenpaar zu verwenden, können Sie zusätzlich PrivateB vor Mitgliederfunktionen schützen. Dies könnte tun, indem a erben wird; Aber ich denke ich bevorzuge John Harrisons comp.lang.c ++ Post unter Verwendung einer const -Klasse.

Interessanterweise haben Sie in C# das Schlüsselwort const, das sich in der statischen Konstant von C ++ übersetzt, im Gegensatz zu Readonly, das nur auf Konstruktoren und Initialisierungen festgelegt werden kann, selbst von Nicht-Konstanten, Ex:

readonly DateTime a = DateTime.Now;

Ich bin damit einverstanden, dass Sie es genauso gut statisch machen könnten, wenn Sie ein vordefiniertes CONT-Array haben. An diesem Punkt können Sie diese interessante Syntax verwenden:

//in header file
class a{
    static const int SIZE;
    static const char array[][10];
};
//in cpp file:
const int a::SIZE = 5;
const char array[SIZE][10] = {"hello", "cruel","world","goodbye", "!"};

Ich fand jedoch keinen Weg um die Konstante '10'. Der Grund ist jedoch klar, dass er weiß, wie man den Zugriff auf das Array durchführt. Eine mögliche Alternative besteht darin, #Define zu verwenden, aber ich mag diese Methode nicht und ich #undef am Ende des Headers, mit einem Kommentar, um dort bei CPP zu bearbeiten, falls eine Änderung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top