inicializovat const pole ve třídě inicializátoru v jazyce C ++

hlasů
68

Mám následující třídy v jazyce C ++:

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

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

Otázkou je, jak mohu inicializovat b v seznamu inicializace, vzhledem k tomu, že nemohu inicializovat uvnitř těla funkce konstruktoru, protože b je const?

To nefunguje:

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

Edit: Případ v bodě je, když mohu mít různé hodnoty bpro různé případy, ale hodnoty jsou známy jako konstantní po celou dobu životnosti instance.

Položena 02/10/2008 v 12:23
zdroj uživatelem
V jiných jazycích...                            


10 odpovědí

hlasů
67

S C ++ 11. Odpověď na tuto otázku se nyní změnilo a můžete ve skutečnosti dělat:

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;
}
Odpovězeno 18/10/2011 v 12:11
zdroj uživatelem

hlasů
30

Stejně jako ostatní řekl, ISO C ++ nepodporuje. Ale můžete jej obejít. Stačí použít namísto std :: vector.

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

class C {
  const std::vector<int> v;
public:
  C():v(a, a+N) {}
};
Odpovězeno 02/10/2008 v 14:52
zdroj uživatelem

hlasů
25

To není možné v současném standardu. Věřím, že budete mít možnost to udělat v C ++ 0x seznamů pomocí Inicializátor (viz Krátký pohled na C ++ 0x , Bjarne Stroustrup, pro více informací o seznamech Inicializátor a dalších příjemných vlastností C ++ 0x).

Odpovězeno 02/10/2008 v 12:31
zdroj uživatelem

hlasů
12

std::vectorpoužívá haldy. Bože, co je to odpad, který by byl jen kvůli o constzdravý rozum kontroly. Smyslem std::vectorje dynamický růst v běhu, není žádný starý syntax kontrola, která by měla být provedena při kompilaci. Pokud nebude růst pak vytvořit třídu zabalit normální pole.

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

ConstFixedSizeArrayFillera ConstFixedSizeArrayjsou opakovaně použitelné.

První umožňuje run-time meze kontroly při inicializaci pole (stejně jako vektor moc), který může později se stal constpo této inicializaci.

Druhá umožňuje pole, které mají být přiděleny uvnitř jiného objektu, které by mohly být na haldě nebo jednoduše v zásobníku v případě, že je místo, kde je objekt. Neexistuje žádná ztráta času přidělení z haldy. Provádí také kompilaci-time const kontrolu na poli.

b_fillerje malá soukromá třída poskytnout inicializační hodnoty. Velikost pole je kontrolována při kompilaci s argumenty šablon, takže není šance, aby šel mimo hrací plochu.

Jsem si jist, že jsou exotičtější způsoby, jak změnit tento. To je počáteční stab. Myslím, že můžete do značné míry nahradit některý z nedostatku kompilátoru s třídami.

Odpovězeno 15/04/2010 v 05:21
zdroj uživatelem

hlasů
8

ISO norma C ++ neumožňuje provedení této akce. Pokud ano, syntaxe by pravděpodobně:

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

Nebo něco podél těchto linek. Z vaší otázky je ve skutečnosti zní jako to, co chcete, je konstantní třída (aka statické) člen, který je pole. C ++ to nechat udělat. Jako tak:

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

Výstupem bytost:

A::a => 0, 1

Teď samozřejmě, protože to je statický člen třídy je stejná pro všechny instance třídy A. Pokud to není to, co chcete, tj chcete každou instanci mít různé hodnoty prvků v poli a, poté děláš chyba, že se snaží, aby se const array začít. Ty by měly být jen to udělat:

#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;
}
Odpovězeno 02/10/2008 v 12:50
zdroj uživatelem

hlasů
4

Kde jsem konstantní pole, je to vždy bylo provedeno jako statické. Pokud můžete přijmout, že tento kód by měl kompilovat a spouštět.

#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;
}
Odpovězeno 02/10/2008 v 12:34
zdroj uživatelem

hlasů
4

Můžete to udělat, že ze seznamu inicializace,

Podívejte se na toto:

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

:)

Odpovězeno 02/10/2008 v 12:28
zdroj uživatelem

hlasů
3

Jak se o emulaci const pole pomocí funkce přistupujícího? To je non-statické (jak jste požadoval), a to nevyžaduje stl nebo jakékoliv jiné knihovny:

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

Protože :: privateB je privátní, to je v podstatě konstantní, mimo :: a máte přístup je podobný poli, např

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

Pokud jste ochotni použít pár tříd, můžete navíc ochránit privateB z členských funkcí. Toho lze dosáhnout tím, dědění a; ale myslím, že bych raději John Harrison je comp.lang.c ++ příspěvek pomocí const třídu.

Odpovězeno 10/06/2011 v 15:52
zdroj uživatelem

hlasů
3

Řešení bez použití haldy se std::vectorje použít boost::array, i když není možné inicializovat členy pole přímo v konstruktoru.

#include <boost/array.hpp>

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

class A {
    const boost::array<int, 2> b;
    A():b(aa){};
};
Odpovězeno 18/05/2010 v 23:24
zdroj uživatelem

hlasů
2

Je zajímavé, že v jazyce C # máte const klíčových slov, která se promítá do C ++ 's statické const, jako protiklad k jen pro čtení, které lze nastavit pouze při konstruktérů a inicializaci, dokonce non-konstant, ex:

readonly DateTime a = DateTime.Now;

Souhlasím, pokud máte const předem definované pole, které by bylo dobré, aby to statické. V tomto okamžiku můžete použít tento zajímavý syntaxi:

//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", "!"};

Nicméně, jsem nenašel cestu kolem konstantní ‚10‘. Důvod je jasný když to potřebuje vědět, jak provádět přístup k poli. Možnou alternativou je použití #define, ale nemám rád tuto metodu, a já #undef na konci záhlaví, s komentářem, aby tam v CPP upravovat i v případě, že změna.

Odpovězeno 28/05/2009 v 18:44
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more