주제
- 메모리 할당
- 멤버 함수 포인터
- 참조자
- switch문
Ex00
주요 개념
- 객체 생성 방식
- 동적 할당
객체 생성 방식의 차이
- newzombie
동적할당
사용- heap 영역
- 이유 : 객체를 생성하고 계속 사용할 것이기 때문
- randomchump
- 일반적인 방식 사용
- stack 영역
- 이유 : 객체를 생성하고 바로 소멸할 것이기 때문
Ex01
주요 개념
- 객체를 배열로 동적할당하기 위해서는 디폴트 생성자가 존재해야한다.
- name 변수 설정
- 해당 변수는 private이므로 setter 함수가 필요
- stringstream
- 문자열을 조작할 수 있는 스트림 클래스
인스턴스명.str("")
와 같이 사용하여 스트림을 초기화 할 수 있다.
Ex02
주요 개념
참조자 (Reference)
- 특정 변수의 실제 이름 대신 사용할 수 있는 별명
- 별도의 메모리 공간을 갖지 않는다.
- 정의 시에 반드시 누구의 레퍼런스인지를 명시해야 한다.
Ex03
- 함수명 뒤에 const 의미 (ex.
void getVariable() const;
)- 해당 함수가 객체의 상태를 변경하지 않는다는 것을 보장
- const 객체만 해당 함수를 호출할 수 있다.
- const 객체는 non-const 함수를 호출할 수도 있다.
- 참조자로 선언한 멤버 변수는 선언과 동시에 초기화를 해주어야 함.
- 초기화 리스트 사용
- HumanA와 HumanB에서 weapon 선언 방식의 차이
- humanA : 생성할 때 weapon을 받음 (참조자)
- humanB : 생성할 때 weapon을 받지 못함. (포인터)
NULL로 초기화.
- attack 함수 구현시 고려 필요.
- 참조자 타입의 변수는
생성할때 초기화
를 해주어야 하기 때문에 B에게는 부적합함.
- const를 리턴하는 함수 내에서 non-const 변수를 return 하면 const로 변환되어 리턴될까?
- non-const 변수가 그대로 return된다.
- 포인터를 리턴하는 함수는
*
를 반환형, 함수명 중에 어느쪽에 붙여야 할까?- 어느 쪽에 붙이던 상관 없다.
char *str
: C에서 일반적인 방식char* str
: C++에서 일반적인 방식
- settype 매개변수에 const를 사용하는 이유?
- 함수 내에서 인자의 값을 변경하지 않기 위해 일반적으로 const형의 매개변수를 받는다.
Ex04
주요 개념
std::ifstream
- input file stream
- 객체 생성 이후, open 멤버함수로 파일을 열거나 객체 생성시에 인자로 파일명을 넘겨줄 수도 있음.
- open 이후에 fail 멤버 함수를 통해 fail비트 또는 bad비트가 켜졌는지를 확인함.
- failbit
- 입력 작업 시 내부적인 논리 오류로 인해 발생되는 오류
- ex) 입력받기를 기다리는 값이 오지 않는 문제
- badbit
- 스트림의 완전성이 깨진 경우(하나의 스트림에 여러 작업이 진행)
- failbit
std::ofstream
- output file stream
- ifstream과 마찬가지로 객체 생성시에 파일명을 바로 넘겨줄 수도 있음.
- 연산자
<<
- 삽입 연산자를 오버로딩 한다.
구현 과정
- infile open
- outfile 생성 후 open
- infile 스트림을 한 줄씩 읽어서 str에 저장
- eof를 만날 때까지 반복
- 한 줄마다 개행문자 추가
- 해당 줄(str)에서 s1을 find
- 찾은 첫 번째 인덱스를 반환
- 해당 인덱스에서 s1을 erase 후 s2를 insert
- s2 길이만큼 뒤로 간 뒤에 다시 find
- pos값이 npos (size_t의 최대값, find가 아무것도 찾지 못했을 때의 반환값)일 때까지 반복
Ex05
주요 개념
멤버 함수 포인터
선언 방법
1
int (*f)(void);
사용 예시
1 2 3 4 5 6 7
int main() { int (*f)(int); f = functionA; // 함수 functionA를 함수 포인터 f에 저장 std::cout << f(5) << std::endl; }
Q&A
다음과 같이 호출한 이유
1
(this->*f[i])();
- 연산자의 우선순위 때문에 함수를 괄호로 감싸야 함.
Ex06
주요 개념
switch문
- case에 일치한다면 다음의 종료조건을 만나기 전까지 레이블을 계속 실행한다.
switch
블록의 끝에 도달한 경우return
문이 발생한 경우goto
문이 발생한 경우break
문이 발생한 경우
요구 사항
- switch문의 case 조건을 만족하면 해당 조건부터 아래의 모든 조건들을 전부 실행해야함.
Q&A
- switch문에서 break의 역할
- switch문은 case를 만족하면 계속 실행하기 때문에 break로 해당 case만 실행되도록 해준다.
- switch문에 break를 사용하는 경우
- 아래는 동일한 코드를 중복해서 작성하지 않고 1,2,3일때 모두 하나의 코드로 실행하는 경우이다.
- 이처럼 switch문을 통해 효율적으로 구성할 수 있다.
- switch문의 이러한 구현을 fallthrough라고 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
int x = 2; int y = 0; switch (x) { case 1: case 2: case 3: y = 10; break; case 4: y = 20; break; default: y = 30; break; }
- 아래는 동일한 코드를 중복해서 작성하지 않고 1,2,3일때 모두 하나의 코드로 실행하는 경우이다.
- case에 break를 사용하지 않으면 다음과 같이 implicit-fallthrough 경고가 발생한다.
1 2 3
Harl.cpp:44:24: error: this statement may fall through [-Werror=implicit-fallthrough=] 44 | this->debug(); | ~~~~~~~~~~~^~
- 이를 방지하기 위해 사용하는
[[fallthrough]]
키워드는 C++17 이후부터 사용이 가능하다. - 대신 이전 버전에서는 주석으로 다음과 같이 fall through임을 명시하여 컴파일 경고를 피할 수 있다.
1 2 3 4 5
/* Falls through. */ /* fall-thru */ /* Else falls through. */ /* FALLTHRU */ /* ... falls through ... */
- 예시
1 2 3 4 5 6 7 8
switch(i) { case 0: this->debug(); // falls through case 1: this->info(); // falls through ... }
- 이를 방지하기 위해 사용하는