클래스에서 const 멤버 변수를 초기화하는 방법은 무엇입니까?


105
#include <iostream>

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

  T1()
  {

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

const 멤버 변수 t를 100 으로 초기화하려고 할 때 .하지만 다음과 같은 오류가 발생합니다.

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

const값을 초기화하려면 어떻게 해야합니까?


8
C ++ 11을 사용하면이 링크를 확인할 수 있습니다. stackoverflow.com/questions/13662441/…
Kapil

답변:


122

const변수를 지정하는 변수 수정 여부. 할당 된 상수 값은 변수가 참조 될 때마다 사용됩니다. 할당 된 값은 프로그램 실행 중 수정할 수 없습니다.

Bjarne Stroustrup의 설명은 이를 간략하게 요약합니다.

클래스는 일반적으로 헤더 파일에서 선언되고 헤더 파일은 일반적으로 많은 변환 단위에 포함됩니다. 그러나 복잡한 링커 규칙을 피하기 위해 C ++에서는 모든 개체에 고유 한 정의가 있어야합니다. C ++에서 객체로 메모리에 저장해야하는 엔티티의 클래스 내 정의를 허용하면 해당 규칙이 깨집니다.

const변수는 클래스 내에서 선언되어야하지만, 그 안에 정의 할 수 없습니다. 클래스 외부에서 const 변수를 정의해야합니다.

T1() : t( 100 ){}

여기서 할당 t = 100은 클래스 초기화가 발생하기 훨씬 전에 이니셜 라이저 목록에서 발생합니다.


3
Here the i = 10 assignment in initializer list happens much before the class initilizaiton occurs.내가 이것을 이해하지 못하는 마지막 진술에 대해 조금 자세히 설명해 주 시겠습니까? 그리고 기본적으로 클래스 내에서 정의를 허용하는 것은 컴파일러 고유의 것입니까?
Chaitanya

3
내가 = 10 과제?
Daniel Daranas 2013-06-12

위의 방식으로 초기화하는 클래스에 상수가 있습니다. 그러나 해당 클래스의 개체를 만들려고하면 operator = function not foundVC ++에서 오류가 발생 합니다. 무엇이 문제일까요?
Rohit Shinde 2014 년

4
귀속없이 다른 사람의 정확한 단어를 사용하는 것을 표절이라고합니다. 적절한 속성을 사용하십시오 - 볼 stroustrup.com/bs_faq2.html#in-classstackoverflow.com/questions/13662441/...
Tanaya

그래, 나는 또한 대답의 코드를 완전히 이해하지 못합니다-도대체 그게 뭔데? cpp 파일 구현에 배치 할 수 있습니까?
Tomáš Zato-Monica 복원

50

글쎄, 당신은 그것을 만들 수 있습니다 static.

static const int t = 100;

또는 멤버 이니셜 라이저를 사용할 수 있습니다.

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

2
그의 용도 (및 / 또는 의도)를 위해 정적으로 만드는 것이 훨씬 낫습니다.
Mark Garcia

@FredLarson 일부 g ++ 버전이 그런 종류의 초기화를 허용하지 않는 것 같습니까? 또는 전혀 허용되지 않습니까?
Chaitanya

3
@Chaitanya : C ++ 11 비 정적 멤버 이니셜 라이저는 gcc 4.7에서 구현됩니다.
Jesse Good

@MarkGarcia가 왜 훨씬 나아 졌습니까? 경우는 필요에있을 수있는 const member기능에서 액세스 할 수 있어야하는 이유 정적 다음 / 객체?
Asif Mushtaq 2016

일반적으로 정적 초보자에게 예제를 제공하는 것은 오해의 소지가 있습니다. 왜냐하면 그들은 해당 클래스의 모든 인스턴스 (객체)에 대해 하나뿐이라는 것을 알지 못할 수도 있습니다.
Muhamed Cicak

30

클래스 내에서 const 멤버를 초기화하는 방법에는 두 가지가 있습니다.

일반적으로 const 멤버의 정의는 변수 초기화가 필요합니다.

1) 클래스 내부에서 const를 초기화하려는 경우 구문은 다음과 같습니다.

static const int a = 10; //at declaration

2) 두 번째 방법은

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

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

3) 선언시 초기화를 원하지 않는 경우 다른 방법은 생성자를 통해 변수를 초기화 목록 (생성자의 본문이 아님)에서 초기화해야합니다. 이럴거야

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

8
이 답변에는 설명이 필요하다고 생각합니다. 클래스 멤버에 정적 키워드를 사용하는 것은 컴파일러를 행복하게 만들기 위해 임의의 구문을 추가하는 것이 아닙니다. 이는 상수 여부에 관계없이 개체의 모든 인스턴스에 대해 변수의 단일 복사본이 있음을 의미합니다. 신중하게 고려해야 할 디자인 선택입니다. 프로그래머는이 상수 클래스 멤버가 주어진 객체의 수명 동안 일정하게 유지 되더라도 여전히 다른 객체에 따라 달라질 수 있다고 결정할 수 있습니다.
opetrenko

동의 .. 정적을 사용하면 모든 객체에 대해 하나의 사본 만 생성됩니다. 설계 선택이라고 언급했듯이. 모든 개체 1과 2에 대한 단일 복사본의 경우 작동합니다. 각 개체에 대한 개별 사본의 경우 3
개가

이 답변은 결과가없는 간단한 구문 변경을 제안하지만 정적으로 변경하는 것은 아닙니다.
Isaac Woods

double 또는 float를 사용해야하는 경우 어떻게해야합니까? 이것은 C ++ 11 표준의 일부입니까?
serup

14

const클래스 의 데이터 멤버를 정적 으로 만들지 않으려면 클래스 const생성자를 사용하여 데이터 멤버를 초기화 할 수 있습니다 . 예를 들면 :

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

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

const클래스에 여러 데이터 멤버가있는 경우 다음 구문을 사용하여 멤버를 초기화 할 수 있습니다.

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

3
나는 이것이 받아 들여진 것보다 더 나은 대답을 제공한다고 생각한다 ....
Ian

1
명확한 예와 복수를 보여주는 변형에 감사드립니다! 독자의 모호함과 추가 조사 / 스크롤을 제거했습니다!
clearlight

13
  1. C ++ 11을 지원하도록 컴파일러를 업그레이드하면 코드가 완벽하게 작동합니다.

  2. 생성자에서 초기화 목록을 사용합니다.

    T1() : t( 100 )
    {
    }

6

또 다른 해결책은

class T1
{
    enum
    {
        t = 100
    };

    public:
    T1();
};

따라서 t는 100으로 초기화되고 변경할 수 없으며 비공개입니다.


3

멤버가 배열 인 경우 일반적인 경우보다 약간 복잡합니다.

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

또는

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

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

2

또 다른 가능한 방법은 네임 스페이스입니다.

#include <iostream>

namespace mySpace {
   static const int T = 100; 
}

using namespace std;

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

단점은 다른 클래스도 헤더 파일을 포함하는 경우 상수를 사용할 수 있다는 것입니다.


1

이것이 올바른 방법입니다. 이 코드를 시도해 볼 수 있습니다.

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

사용하는 경우 C++10 Compiler or below선언시 cons 멤버를 초기화 할 수 없습니다. 따라서 여기에서는 const 데이터 멤버를 초기화하기 위해 생성자를 만들어야합니다. 또한 T1():t(100)즉시 메모리를 얻으려면 이니셜 라이저 목록 을 사용해야합니다 .


0

static이 클래스 멤버 변수의 초기화를 가능하게하기 위해 추가 할 수 있습니다 .

static const int i = 100;

그러나 클래스 선언 내부에서 사용하는 것이 항상 좋은 방법은 아닙니다. 해당 클래스에서 설치 한 모든 개체는 인스턴스화 된 개체의 범위 메모리 외부에있는 내부 메모리에 저장된 동일한 정적 변수를 공유하기 때문입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.