문제

C ++에는 다음 수업이 있습니다.

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

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

문제는 B이기 때문에 생성자의 기능 본문 내부에서 초기화 할 수 없다는 점을 감안할 때 초기화 목록에서 B를 초기화하는 방법입니다. const?

이것은 작동하지 않습니다 :

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

편집 : 사례는 다른 값을 가질 수있는 시점입니다. b 다른 경우의 경우, 값은 인스턴스의 수명에 대해 일정하게 알려져 있습니다.

도움이 되었습니까?

해결책

다른 사람들이 말했듯이, ISO C ++는이를 지원하지 않습니다. 그러나 당신은 그것을 해결할 수 있습니다. 대신 std :: 벡터를 사용하십시오.

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

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

다른 팁

C ++ 11을 사용하면이 질문에 대한 답이 이제 변경되었으며 실제로 할 수 있습니다.

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

현재 표준에서는 불가능합니다. 초기화 목록을 사용하여 C ++ 0X 에서이 작업을 수행 할 수 있다고 생각합니다 ( C ++ 0x를 간략하게 살펴 봅니다, Bjarne Stroustrup의 초기화 목록 및 기타 멋진 C ++ 0X 기능에 대한 자세한 내용).

std::vector 힙을 사용합니다. 이런, 단지 const 위생 점검. 요점 std::vector 컴파일 타임에 수행 해야하는 오래된 구문 검사가 아니라 런타임에 동적 성장입니다. 성장하지 않으려면 일반 배열을 감싸는 클래스를 만듭니다.

#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 그리고 ConstFixedSizeArray 재사용 가능합니다.

첫 번째는 배열을 초기화하는 동안 런타임 바운드를 확인할 수 있습니다 (벡터가 벡터와 동일). 나중에 const 이 초기화 후.

두 번째는 배열을 할당 할 수 있습니다 내부에 히프에있을 수있는 또 다른 물체 또는 단순히 객체가있는 경우 스택에있을 수 있습니다. 힙에서 할당하는 시간 낭비는 없습니다. 또한 배열에서 Compile-Time Const 확인을 수행합니다.

b_filler 초기화 값을 제공하는 작은 개인 클래스입니다. 배열의 크기는 템플릿 인수와 함께 컴파일 타임에서 확인되므로 경계를 벗어날 가능성이 없습니다.

나는 이것을 수정하는 더 이국적인 방법이 있다고 확신합니다. 이것은 초기 찌르기입니다. 나는 당신이 컴파일러의 수업 끝을 거의 보충 할 수 있다고 생각합니다.

ISO 표준 C ++를 사용하면이를 수행 할 수 없습니다. 그렇다면 구문은 아마도 다음과 같습니다.

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

또는 그 줄을 따라 무언가. 질문에서 실제로 원하는 것은 배열 인 상수 클래스 (일명 정적) 멤버 인 것 같습니다. C ++는 당신이 이것을 할 수있게합니다. 그렇게 :

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

출력은 다음과 같습니다.

A::a => 0, 1

물론 이것은 정적 클래스 멤버이기 때문에 클래스 A의 모든 인스턴스에 대해 동일합니다. 그렇지 않으면 원하는 것이 아니라면 A의 각 인스턴스가 배열 A에서 다른 요소 값을 갖기를 원합니다. 배열을 시작하려는 실수. 당신은 이것을해야합니다 :

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

내가 일정한 배열이있는 곳에서는 항상 정적으로 이루어졌습니다. 이를 수락 할 수 있다면이 코드는 컴파일 및 실행해야합니다.

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

초기화 목록에서 그렇게 할 수 없습니다.

이것을 살펴보십시오 :

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

:)

힙을 사용하지 않고 솔루션 std::vector 사용하는 것입니다 boost::array, 생성자에서 배열 멤버를 직접 초기화 할 수는 없습니다.

#include <boost/array.hpp>

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

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

액세서 기능을 통해 Const 배열을 에뮬레이션하는 것은 어떻습니까? 비 정적 (요청대로)이 아니며 STL이나 다른 라이브러리가 필요하지 않습니다.

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

a :: privateb는 개인이기 때문에 a :: 외부에서 효과적으로 일정하며 배열과 유사하게 액세스 할 수 있습니다.

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

한 쌍의 클래스를 기꺼이 사용하려는 경우 회원 기능으로부터 PrivateB를 추가로 보호 할 수 있습니다. 이것은 a를 상속함으로써 수행 될 수있다; 그러나 나는 선호한다고 생각한다 Const 클래스를 사용한 John Harrison 's comp.lang.c ++ 게시물.

흥미롭게도, C#에는 C ++의 정적 const로 변환되는 키워드 Const가 있습니다.

readonly DateTime a = DateTime.Now;

Const 사전 정의 된 배열이 있으면 정적으로 만들 수도 있습니다. 이 시점 에서이 흥미로운 구문을 사용할 수 있습니다.

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

그러나 나는 상수 '10'을 둘러싼 길을 찾지 못했습니다. 그 이유는 분명하지만 배열에 대한 액세스를 수행하는 방법을 알아야합니다. 가능한 대안은 #define을 사용하는 것이지만, 나는 그 방법을 싫어하고 헤더 끝에 나는 #undef를 싫어하고, 변경된 경우에도 CPP에서 편집 할 주석을 가지고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top