티스토리 뷰

Programming/C++

[c++]const

쩨리쩨리 2018. 3. 8. 12:49
반응형

* const(상수화 멤버)

- c++에서는 멤버 필드 중에 값을 변경하지 못하는 상수화 멤버 필드와 메소드 내에서 객체의 상태를 변경하지 못하는 상수화 메소드를 지정할 수 있다.

- 상수화 멤버 필드는 선언문 앞에 const 키워드를 붙여주고 상수화 멤버 메소드는 입력 인자를 명시하는 괄호 뒤에 const 키워드를 붙여준다. ex : int tistory() const;

- 예를들어, 학생 생성 시 학번을 부여하고 이후에는 학번을 변경하지 못하게 하고자 한다면 상수화 멤버 필드로 사용할 수 있다. 상수화 멤버 필드는 생성자 정의문에서 초기화 기법을 사용하여 값을 지정해야 한다. 초기화 기법은 생성자 메소드의 입력 인자를 명시하는 함수 뒤에 콜론(:)을 붙인 후에 초기화할 멤버 이름을 명시하고 괄호에 초기화할 구문을 작성한다.

- 상수화한 객체의 상태를 확인하는 메소드들은 객체의 상태를 바꾸지 않기 때문에 상수화 메소드로 정의하는 것이 높은 데이터 신뢰성을 추구 할 수 있다.

- 상수화 멤버 메소드에서 다른 멤버 메소드(상수화로 지정하지 않은 메소드)를 호출하는 것은 데이터 신뢰성에 문제가 되어 컴파일 오류가 생긴다.

 

 

 

* const 종류

1. const field : 객체선언 할 때 선언과 동시에 초기화를 해줘야하는데 const에선 할 수 없음. 초기화하는 법은 '콜론 초기화 기법'을 이용해야 한다. const 필드에선 값을 읽는 것만 가능하다.
2. consst method : 필드의 값을 함수에서 읽기만 가능하다. 쓰고 사용 할 수는 없다.

3. const Object : 고정된 객체를 사용할 수 있다. 읽기만 가능하다.

 

 

 

* const 특징

1. const는 한번 설정한 값을 바꾸지 못하기 때문에 캡슐화가 가능하며 데이터 보호가 가능하다. 디폴트처럼 디폴트된 기능은 못 바꾸듯이 const도 한번 상수화 시키면 멤버 및 함수 기능을 바꿀수 없다.

2. 캡슐화된 const는 class 내에서 어떻게 정의하던 외부에서 읽어오거나 사용할 수 없다.

3. const는 const 끼리만 쓸수 있다. 즉, const로 보낸 것은 const로만 받을 수 있다.

4. const 객체는 const 멤버만 사용 가능하다.

5. 함수명이 같은 const 함수와 일반 함수가 있다. 만약 함수쪽으로 인자를 넘긴다면 const가 아닌 일반 함수쪽으로 가게된다. 왜냐하면 const보다 일반 함수쪽이 우선순위가 더 높기 때문이다. (우선 순위가 존재한다.)

 

 

 

 

* 문제 1 : main에서 객체를 만든다.  인스턴스 객체를 인자로 함수에 보낸다. 이때 보내는 함수는 static 함수이다. 이때, static에서 인스턴스 함수를 받을 수 있는 방법을 레퍼런스 변수를 이용해 코딩하시오.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <iomanip>
using namespace std;
 
/*
static method
1. class를 통틀어서 오직 하나다.(많이 쓰는 방법)
2. this pointer가 존재하지 않는다.(객체를 만들수 없기 )
3. instance field를 사용할 수 없다.
4. 클래스명::메소드() 이렇게 사용도 할 수 있고,
객체,메소드() >> 객체를 만든후에 가능
*/
 
class A {
 
    int a;
 
 
public:
    A() { a = 100; }
    static void disp(const A& th) {
 
 
        cout << "static method" << th.a << endl;
    }
 
 
};
 
void main() {
    //A::disp();
    A aa;//객체 등록
    aa.disp(aa);//static 함수에 객체를 직접 넘겨줘야함
                //자기자신의 객체인 것을 구분하기 위해 객체를 직접 넣음
}
cs

 

 

* 풀이

static은 객체가 등록되지 않기 때문에 아무리 객체를 여러개 보내더라도 static 함수에서 모든 객체 값과 주소들이 섞여 모든 객체가 공유 가능하다. (static은 객체를 받지 못하므로 this를 쓸수 없다. 자기 객체 구분하지 못함.)하지만 인스턴스에서는 자기자신의 값과 주소를 구별하는 this가 있기 때문에 값을 보내면 정확하게 넣은 값을 인식 할 수가 있다. static은 인식을 못하기 때문에 주소를 가리키는 레퍼런스 변수 선언이 필수 이다. 레퍼런스 변수로 각 객체가 넣은 값과 주소를 인식해야한다.

 

 

 

* 문제 2 : main에서 객체를 만든다.  인스턴스 객체를 인자로 함수에 보낸다. 이때 보내는 함수는 static 함수이다. 이때, static에서 인스턴스 함수를 받을 수 있는 방법을 포인터를 이용해 코딩하시오.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
- c++ 버전
 
#include <iostream>
#include <iomanip>
using namespace std;
 
/*
static method
1. class를 통틀어서 오직 하나다.(많이 쓰는 방법)
2. this pointer가 존재하지 않는다.
3. instance field를 사용할 수 없다.
4. 클래스명::메소드() 이렇게 사용도 할 수 있고,
     객체,메소드() >> 객체를 만든후에 가능
*/
 
class A {
 
    int a;
 
 
public :
    A() { a = 100; }
    static void disp(A *th) {
        
 
        cout << "static method" <<th->a<< endl;
    }
 
 
};
 
void main() {
    //A::disp();
    A aa;//객체 등록
    aa.disp(&aa);//static 함수에 객체를 직접 넘겨줘야함
    //자기자신의 객체인 것을 구분하기 위해 객체를 직접 넣음
}
cs

 

 

 

 

 

 

 

* 풀이

main에서 객체를 선언한 뒤 class 에서 객체를 등록하면 static에서는 그 객체를 인식하지 못한다. 즉, 객체를 받을 수가 없다. 왜냐하면 static은 컴파일 당시 제일 먼저 메모리를 배정하기 때문에 인스턴스 구역에서 선언된 객체가 뒤에 생성된다. 따라서 static에서 객체를 인식하지 못한다. 객체를 static 함수에 보내고 싶으면 객체의 주소를 보낸뒤 그 주소를 가리키는 포인터(레퍼런스 변수)를 만든 뒤 그 주소를 받게한다. 그러면 그 포인터는 객체의 주소를 가리키고 있기 때문에 주소의 값도 가리킬 수 있다. 출력할 때에는 포인터가 객체의 주소를 가리키도록 하면 값이 출력 가능하다.

 

 

 

 

 

* 문제 3 : main에서 const를 이용하여 static 함수를 호출했다. const는 상수라서 처음부터 고정된 값이 있기에 초기화를 할 수 없는데, const를 이용하여 초기화를 할 수 있는 코딩을 하시오.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <iomanip>
using namespace std;
 
/*
static method
1. class를 통틀어서 오직 하나다.(많이 쓰는 방법)
2. this pointer가 존재하지 않는다.
3. instance field를 사용할 수 없다.
4. 클래스명::메소드() 이렇게 사용도 할 수 있고,
     객체,메소드() >> 객체를 만든후에 가능
*/
 
class A {
 
    static int a;//링크
 
 
public :
    A() { a = 100; }
    static void disp() {
        //1.main 밖에 쓰는 변수: 전역변수
        //static 메소드는 static 필드를 관리하기 위해 존재함
        
 
        cout << "static method" <<a<< endl;
    }
    
 
};
int A::a = 300;//class 이름 {}는 멤버라는 뜻
               //a 선언, static 변수를 쓰려면 링크와 선언을 같이 해줘야함
               //static 변수를 쓰기위해선 외부에서 멤버 선언 필수
 
void main() {
    A::disp();

 

    A aa;//객체 등록
    aa.disp();
    
}
cs

 

* 풀이

- static 필드와 함수가 가장 먼저 메모리가 할당된다. class 내부에 있는 a와 class 외부에 있는 a는 같은 a이다. a변수를 선언 및 값 300을 넣는 행위는 외부에서 하고 a 변수를 Aclass와 연결하는 행위는 클래스 내부의 static int a;에서 한다. 따라서 컴파일 맨처음 부분부터 a는 300을 가지는 고정값이 된다. static에서 메모리 할당뒤에 main이 실행된다. main에서 const 함수를 호출한다. a 값이 처음부터 300을 가지고 있었으니 함수를 호출하면 300이 출력된다. 다음 main으로 다시 돌아가 A 타입의 aa 객체를 등록한다. aa 객체는 객체를 등록하러 생성자쪽으로 가게 된다. 생성자에서 a 초기값으로 100을 넣고 있으니 a 값이 100으로 초기화 되게 된다. 따라서 aa 객체를 받는 static 함수를 호출하면 100이 출력된다.

 

 

 

 

 

* static의 이해

static은 main 함수가 실행되기전에 제일 먼저 메모리를 잡고 기능을 처리한뒤 다른 인스턴스 필드와 함수를 처리한다. 이때 static 외부에 선언된 변수는 전역변수로 모든 객체들이 공유가 가능하다. static은 객체를 만들지 못하기 때문에 자기자신의 객체를 가리키는 this를 쓸수 없다. 따라서 객체들이 자기 자신의 메모리값을 가리키지 못하기 때문에 객체들의 값이 각각 자기 자신의 객체를 인식하지 못하고 메모리를 모든 객체들과 공유할 수 있게 된다.

 

 

 

반응형

'Programming > C++' 카테고리의 다른 글

[c++] 상속  (0) 2018.03.09
[c++]has~a 관계를 이용한 사람수 제한없는 성적프로그램  (0) 2018.03.08
[c++]소멸자함수  (2) 2018.03.07
[c++]복사생성자  (0) 2018.03.07
[c++]class, 생성자  (0) 2018.03.07
댓글
공지사항