본 글을 개인적 학습을 위한 글입니다. 틀린 내용이 있을 시 마구 지적해주시면 감사합니다.
이번 글은 C++의 한 층 더 심화적인 내용을 다룹니다. 앞의 글들에서 다루었던 내용을 다시 살펴보는 시간도 가집니다. 그렇기에 오늘은 자세한 설명을 하기 보다는 코드와 주석을 통해 글을 진행해보도록 하겠습니다.

컴파일 시 그 주소를 지워버리고 호출한 위치에 함수가 복사, 붙여넣기 된다.
특징 : 실행 파일이 길어지지만, 속도가 빨라진다. (함수를 호출하는 시간이 사라짐)
일반적인 함수의 작동 원리
함수를 컴파일하면 그 내용을 호출해서 실행 한다. (함수의 원본만 존재하고, 이를 대신할 주소가 존재한다.)
// 인라인 덧셈 함수
inline int add(int a, int b) {
return a + b;
}
int main() {
int x = 5, y = 3;
std::cout << "Sum: " << add(x, y) << std::endl;
return 0;
}
지난 글에서 언급되었던, 연산자 중복(Operator Overloading)에 대해 각각의 케이스를 확인하면서 조금 더 자세히 알아보는 시간을 가져보겠습니다.
보통 선언은 크게 두 가지로 나뉘어집니다.
하지만 가능하면 멤버 함수로 작성하는 것이 좋다. (캡슐화의 원칙)
먼저 2항 연산자의 오버라이딩부터 세세하게 보겠습니다.
c = a + b;
// 아래는 컴파일러에 의한 변환
c = a.+(b);
// 즉 피연산자 b가 인자로써 전달된다.
Power Power::operator+(Power op2){
Power tmp;
tmp.kick = this->kick + op2.kick;
tmp.punch = this->punch + op2.punch;
return tmp;
}
예외 사항
b = 2 + a; // 아래는 컴파일러가 변환한 형태 b = 2.+(a); // 하지만 이 형태는 불가 b = +(2, a); // 이 형태는 가능 // 즉, 2와 a를 각각 인자로 전달한다. (이 경우에, 전역 함수를 이용한다.)Power operator+(int op1, Power op2){ Power tmp; tmp.kick = op1 + op2.kick; tmp.punch = op1 + op2.punch; return tmp; } // 이후 이 function을 friend keyword로 작성한다. // 이렇게 전역 함수를 사용하면, 예외뿐만 아니라 모든 경우에 사용할 수 있다.
a == b;
// 아래는 컴파일러에 의한 변환
a.==(b); // 피연산자 b가 인자로써 전달된다.
bool Power::operator==(Power op2){
if(kick == op2.kick && punch == op2.punch){
return true;
}
return false;
}
c = a += b // 물론 보통 이 형태를 사용하지는 않는다.
// 아래는 컴파일러에 의한 변환
c = a.+=(b);
Power Power::operator+=(Power op2){
kick = kick + op2.kick;
punch = punch + op2.punch;
return *this; // 자기 자신을 다시 내보낸다.
}
단항 연산자의 종류는 두 가지로 분류됩니다. 또한 연산자 중복 방식은 이항 연산자의 경우와 거의 유사합니다.
Power Power::operator++(){
// kick과 punch는 a의 멤버
kick++;
punch++;
return *this; // 변경된 객체 자신(객체 a) 리턴
}
Friend로 작성하기
++a; // 아래는 컴파일러에 의한 변환 ++(a);Power operator++(Power& op){ op.kick++; op.punch++; return op; }
Power Power::operator++(int x){
Power tmp = *this; // 증가 이전 객체 상태 저장
kick++;
punch++;
return tmp; // 증가 이전의 객체(객체 a) 리턴
}
Friend로 작성하기
a++; // 아래는 컴파일러에 의한 변환 ++(a, 0); // '0'은 의미 없는 값으로 전위 연산자와 구분하기 위해 사용함Power operator++(Power& op, int x){ Power tmp = op; op.kick; op.punch++; return tmp; }
!a;
// 아래는 컴파일러에 의한 변환
a.!(); // 매개 변수는 없다.
bool Power::operator!(){
if(kick == 0 && punch == 0) return true;
return false;
}
보통 배열에서 사용되는 인덱스 연산자입니다.
T & operator[](int idx){
return m_data[idx];
}
// reference를 return하기 때문에 R/W 모두 가능한 형태
이미 이전의 글로 살펴 보았던 대입 연산자와 복사 생성자를 코드로써 다시 한 번 더 살펴보도록 하겠습니다. 아주 중요한 것이기에 꼭 이해해야 합니다. 먼저, Assignment와 Copy Constructor를 구분해야 합니다.
// 아래는 Assignment Operator의 코드입니다.
MyString& MyString::operator=(const MyString & str){
// self-assignment check
if(this == &str)
return *this;
// if data exists in the current string, delete it
if(m_data) delete [] m_data;
m_lenght = str.m_length;
// copy the data from str to the implicit object
m_data = new char[str.m_length];
for(int i = 0; i < str.m_lenght; i++){
m_data[i] = str.m_data[i];
}
// return the existing object so we can chain this operator
return *this;
}
C++이라는 프로그래밍 언어에 대해 굵직한 것들만 빠르게 다루다보니, 어느새 이 시리즈의 끝이 다가오는 것 같습니다. 다음 글에서는 함수의 바인딩, 가상 함수, 템플릿 등 조금 더 실전적인 부분들에 대해 다루어보도록 하겠습니다. 긴 글 읽어 주셔서 감사합니다.