강의 흐름
- 정적 멤버 변수와 정적 멤버 함수의 개념 설명
- C++에서 함수의 호출 방식 3가지 체크
전날 복습
- 객체가 만들어질 때 생성자 반드시 필요하다.
- 내가 만들지 않으면 자동으로 컴파일러 만들어준다.
- 생성자를 반드시 내가 만들어줘야 하는 경우 2가지
- const형 변수가 있는 경우
- 참조형(&) 변수가 있는 경우
- 2가지 경우 - 생성자를 만들 시 생성자 초기화 리스트를 통해서만 초기화 가능
- { } 중괄호 블록은 범위를 지정하는 데 사용 = scoupe라고 부른다.
- 객체는 scoupe안에서만 통용되는 애다. - scoupe 빠져나갈 때 없어진다.
정적 멤버 변수
지정 형식 - static int count;
특징 1. 정적 멤버 변수는 클래스 밖에서 초기화해줘야 한다.
특징 2. 정적 멤버 변수의 위치는 클래스 영역이다. ( = 클래스 변수 )
8~11번 line - 일반 멤버 변수와 정적 멤버 변수가 있고
17~21번 line - 객체가 생성될 때마다 count++ 해준다고 한 상태에서
객체 a1, a2, a3를 생성하는 상황을 가정해보면
a1, a2, a3 객체의 메모리에는 각각 일반 멤버 변수들( name, age, grade, classnum)이 자리 잡고 있을 것이고,
그 뒤에 정적 멤버 변수 count도 같이 자리 잡고 있는 것이다? 결론부터 말하면 NO!
정적 멤버 변수 count가
만약 일반 멤버 변수와 같이 객체 안에 자리 잡고 있다면 객체가 생길 때마다 +1 해주는 것이므로
a1에서 count=1 /// a2에서 count = 1 /// a3에서 count =1 이 될 것이다.
일반 멤버 변수와 다를 것이 없어진다.
그렇다면 정적 멤버 변수 count는 어디에 있는 것인가?
static 변수 - 정적 변수는 객체에 섞여있지 않고, 클래스 영역이라는 곳에 하나만 만들어진다.
그 공간을 객체들이 공유해서 사용하는 것이다.
객체에 속해있지 않고 클래스에 속해있다고 하여서 정적 변수를 ( = 클래스 변수 )라고도 한다.
특징 3. 객체를 통해서 접근하지 않아도 클래스로 바로 접근 가능하다.
일밤 멤버 변수는 객체를 생성하고 그 객체를 통해서만 접근할 수 있지만,
static 변수는 클래스에 속해있기 때문에, 객체를 통해서 접근하지 않아도 바로 접근할 수 있다.
60번 Line -> 57번 Line
a1.GetCount() --- 변경 가능 ---> Student :: Count로 가능!
실제 사용하는 경우 –
ex 게임에서 맵에 몬스터 개수 제한 줄 경우! 몹 200마리 이하로 유지할 때
ex 객체들 통제할 때 count 만 바꿔주면 모든 객체에 영향
정적 멤버 함수
지정 형식 : static int add( ) { }
특징 1. 정적 멤버 변수와 같이 객체에 속해있지 않고 클래스 영역에 속해 있다. ( = 클래스 함수 )라고 한다.
특징 2. 정적 멤버 함수 안에서는 일반 멤버 변수, 함수에 접근 불가능
접근이 불가능한 이유는?
- 일반 멤버 함수는 객체가 만들어질 때 생기는 것인데, ( 객체 생겨야 호출 가능 )
- 정적 멤버 변수나 함수는 객체가 만들어지지 않아도 생기는 것이다.( 객체 생기지 않아도 호출 가능 )
없는 거에 접근하는 것이 되므로 - 정적 멤버 함수 안에서 - 일반 멤버 함수, 변수사용 불가능 X
특징 3. 객체를 통해서 접근하지 않아도, 클래스를 통해서 접근 가능하다. +객체를 통해서도 호출 가능
28번 Line -- c.add(a, b)처럼 객체를 통해서 함수를 호출해서 사용해야 하는 - 일반 멤버 함수
29번 Line -- Utility::sub(a, b)처럼 객체 생성 없이도 클래스를 통해 함수를 호출해서 사용하는 - 정적 멤버 함수
14번 Line -- sub( )는 정적 멤버 함수
32번 Line -- 정적 멤버 함수는 객체를 통해서 호출하는 방식도 사용 가능 - c.sub(a, b) 도 가능
함수 호출 방식
먼저 함수 = function의 구성 요소
1. returntype
- 함수 연산을 끝내고 반환 값 어떤 타입인지 지정 필요
- return 값없으면 void
- return 값있으면 함수 내부에 return 반드시 필요!
2. 함수명( 매개변수 )
- 함수명 add
- 매개변수 ( int a, int b)
3. 명령어
- int sum = a + b;
- return sum;
함수의 값을 전달하는 3가지 방법
함수의 매개변수에 - 인자 값을 - 전달하는 3가지 방법
- call by value ( 값에 의한 호출 )
- call by address ( 주소 값에 의한 호출 )
- call by reference ( 참조 값에 의한 호출 )
인자가 -> 매개변수로 전달
이때 전달될 수 있는 인자의 값 - 3가지에 따라 명칭이 다르다.
먼저 인자 ( argument )와 매개변수 ( parameter )의 구분
main에 a, b랑 ( = 인자 )
add함수의 a, b랑 ( = 매개변수 ) 다름!
이름만 같은 애일뿐 강남 사는 a, b 제주도 사는 a, b각자의 스쿠프 { } 안에서만 존재하고 끝나면 사라짐
1. call by value - 값에 의한 호출
main에서 생성된 int a, b - 인자 값으로 a와 b 가 -
add 함수를 호출하면서 --- add 함수의 매개변수로 전달 되게 된다.
이때 전달되는 것이 20과 30이라는 값으로 전달된다.
이처럼 함수를 호출하면서 인자 값을 -> 함수의 매개변수로 전달하는 것을 call by value라고 한다.
2. call by address - 주소 값에 의한 호출
main에서 생성된 int a, b - 여기에서는 인자로 a와 b의 값이 아닌 - 인자로 &a, &b 가- 변수 a와 b의 주소 값이
padd 함수를 호출하면서 --- padd 함수의 매개변수로 전달 되게 된다.
이때 전달되는 것이 20과 30이라는 값이 아닌 20이 저장되어있는 주소 값과 30이 저장되어있는 주소 값으로 전달된다.
이처럼 함수를 호출하면서 인자의 주소 값을 -> 함수의 매개변수로 전달하는 것을 call by address라고 한다.
+@
21번 Line - int형 주소 값을 저장하는 포인터형 변수 pa, pb 만들어지고 ( * 포인터 형 지정자로 사용 )
21번 Line - 거기에 a변수의 주소 값&a, b변수의 주소 값&b가 인자 값으로 전달된다.
22번 Line - pa라는 변수에는 &a 가 저장되어있는데 *pa를 하면 *&a와 같다.( * 포인터 연산자로 사용 )
22번 Line - *&a => a의 주소 값을 저장하고 있는 공간을 의미 = 이것은 곧 a와 같다. ( *&a = a )
포인터 연산자의 역할 -> 해당 주소 위치에서부터 할당받은 공간을 의미!
temp = *pa + *pb;
temp = *(&a) + *(&b);
temp = *&a + *&b;
temp = a + b;
call by address의 체크 포인트!
- 여기서 넘어온 a의 주소 값 --- &a는 main안에 있는 a의 주소 값이다.
- 기본적으로 main에 있는 변수 a와 b는 다른 곳에서 접근할 수 없다.
- main의 스쿠프{ } 안에서만 사용하고 없어지는 애인데,
- padd 함수 안에서 - 넘어온 주소 값을 가지고 - main의 변수 a와 b에 접근 가능하다 - 영향을 줄 수 있다.
- 이런 상황을 결합도가 올라간다고 말하며, 좋은 것이 아니다.
3. call by reference
내부적으로 돌아가는 방법은 call by address와 동일
main에서 생성된 int a, b - 여기에서는 인자로 a와 b의 값이 아닌 - 인자로 &a, &b 가 = 변수 a와 b의 주소 값이
refadd 함수를 호출하면서 --- refadd 함수의 매개변수로 전달 되게 된다.
이때 전달되는 것이 20과 30이라는 값이 아닌 20이 저장되어있는 주소 값과 30이 저장되어있는 주소 값으로 전달된다.
이처럼 함수를 호출하면서 인자의 주소 값을 -> 함수의 매개변수로 전달하는 것을 call by reference라고 한다.
call by reference의 체크 포인트!
- refa , refb라는 메모리 공간이 새로 생기는 것이 아니다.
- a, b를 가리키는 별칭이 하나 더 생긴 것이다. - 접근할 수 있는 방법만 하나 더 생긴 것이다.
- 참조형도 매개 변수로 주소 값이 들어오는데, 한번 지정되면 변경 불가능하다.
- 한 번 연결되는 순간 바꿀 수 없다. - fix 시켜버린다.
- 포인터형은 전달받은 주소 값 변경 가능
객체를 매개변수의 인자로 전달할 경우 :: 참조형으로 전달하는 것이 유리하다
A 클래스가 있고
2가지의 함수를 만들고
출력 TEST
함수 addclassA는 객체의 값을 전달받는 것으로 그대로 입력된다.
int 3개 12byte ( a )와 int 3개 12byte ( b ) 그대로 대입 - 24byte가 공간 차지.
함수 addclassRefA는 객체의 주소 값 만들 전달받는 것이다.
객체의 크기가 12byte 이던지 1,200byte 이던지 상관없이 주소 값을 저장할 공간 4byte만 차지!
이렇듯 참조형으로 전달하면 메모리면에서 유리 - 속도 향상에도 기여
메모리면에서 유리, 한 번 연결되면 변경 불가능한 특징 이용.
참조값을 주소 값이라고 하진 않는다. --- 내부적으로는 주소 값이 맞지만 --- 참조 값은 변수를 가리키는 값이라고 한다.
위험성도 존재 – 전달된 주소 값으로 main의 함수에 접근 가능하다는 것.
review
이번 강의에서 기억 남는 부분은 함수의 매개변수에 인자 값을 전달하는 3가지 방법!
call by value // call by address // call by reference
객체의 값을 // 객체의 주소 값을 // 참조값 - 변수를 가리키는 값을 전달하는 방법!
참조형의 특징에 대해 더 알게 되었고,포인터 형과 참조형. 또 만나니 반가웠다 :)
이번 강의에서 정적멤버변수는
클래스 밖에서 초기화를 해줘야되는 부분과 초기화하는 형식도 알게 되었다.
클래스 내부에서 선언 -> static int Count;
클래스 밖에서 초기화 -> Student :: Count = 0;
이 부분 말고는 정적 멤버 함수 내부에는 일반 멤버 변수와 함수는 사용 못한다는 점
클래스 영역에 존재해서 객체 생성 없이 클래스로 접근 가능하다는 점
java에서의 Static 변수, 함수 사용과 비슷해서 이해하기 수월했다.
클래스를 통해 함수 호출하는 법 - 추가적으로 체크 - Utility :: add(a, b); 이런 식으로 호출!
흐아.. 정리를 하며 복습이 되니까 다시 보는 면은 좋은데...
시간이 오래 걸려서 다른 공부할 시간이 줄어든다.
나중에 참고용으로만 볼 생각하고
알았던 부분은 생략하고 새로운 부분들만 추려서 올려야 하나 생각도 든다.
현재 생각은 이 글을 보며 나중에 혹시라도 남을 가르쳐 줄 상황을 생각하며 글을 작성하고 있다.
가르쳐 주면서 나도 더 배우고, 개념을 더 단단하게 세울 수 있을 것이니까.
후후 고민을 더 해봐야겠다.
'Back-end > C++' 카테고리의 다른 글
21.03.17 - 객체 배열, 동적 객체, 개념 플러스(GC,Malloc,Cin) (0) | 2022.03.24 |
---|---|
22.03.16 - this 포인터, 네임맹글링(오버로딩), 배열 (0) | 2022.03.24 |
22.03.14 - 포인터형, 참조형, const형 변수 (0) | 2022.03.18 |
22.03.11 - 생성자 초기화 리스트, 포인터형과 참조형 (0) | 2022.03.16 |
22.03.10 - 캡슐화, 객체, 접근 제어자, Set/Get함수 (0) | 2022.03.13 |