C언어 기반의 C++

함수 오버로딩(Function Overloading)

함수 호출 시 전달되는 인자를 통해서 호출하고 하는 함수의 구분이 가능하기 때문에 매개변수의 선언 형태가 다르면, 동일한 이름의 함수 정의가 가능하다.

매개 변수의 디폴트 값(Default Value)

C++ 함수에는 디폴트 값을 설정할 수 있는데 디폴트 값은 기본적으로 설정되어 있는 값을 의미한다.

전달되는 인자는 왼쪽부터 채워져 나가고, 부족분은 디폴트 값으로 채워진다.

반드시 오른쪽 매개변수의 디폴트 값부터 채우는 형태로 정의해야 한다.

인라인(inline) 함수

매크로 함수

  • 일반적인 함수에 비해 실행속도의 이점이 있다.
  • 하지만 정의하기가 어렵다.

매크로 함수의 단점을 해결할 수 있는 것이 인라인 함수이다.

#include <iostream>

template <typename T>
inline T SQUARE(T x)
{
    return x * x;
}

int main(void)
{
    std::cout << SQUARE(5.5) << std::endl;
    std::cout << SQUARE(12) << std::endl;
    return 0;
}

매크로를 이용한 인라인화는 전처리기에 의해서 처리되지만, 키워드 inline을 이용한 함수의 인라인화는 컴파일러에 의해서 처리가 된다.

컴파일러는 자체 판단으로 성능에 해가 된다고 생각하면 인라인 키워드를 무시하거나 일부 함수를 인라인화 시키기도 한다.

이름 공간(namespace)

이름 공간은 특정 영역에 이름을 붙여주기 위한 문법적 요소이다.

동일한 이름 공간에 정의된 함수를 호출할 때에는 이름공간을 명시할 필요가 없지만 다른 이름 공간에 정의된 함수를 호출 할 때는 이름 공간을 명시해야 한다.

이름 공간의 중첩

이름 공간 안에 다른 이름 공간이 삽입될 수 있다.

using을 이용한 이름 공간의 명시할 수 있다.

using namespace std;

이름 공간의 별칭을 지정해 줄 수 있다.

namespace ABC=AAA::BBB::CCC;

지역변수의 이름이 전역변수의 이름과 같을 경우, 전역 변수는 지역벼눗에 의해 가려진다. 범위 지정 연산자(Scope Resolution Operator)를 이용해 전역 변수에 접근할 수 있다.

int val = 100;

{
	int val = 20;
	val += 3; // local
	::val += 7; // global
}

bool 형

C++에서는 기본 자료형으로 bool 자료형을 사용할 수 있어, 키워드 truefalse를 사용할 수 있다.

참조자(References)

int &num = num1;

참조자는 자신이 참조하는 변수를 대신할 수 있는 또 하나의 이름이다. 즉, 별칭을 하나 붙여주는 것이다.

  • 참조자를 대상으로 참조자를 선언하는 것도 가능하다.
  • 참조자는 변수에 대해서만 선언이 가능하고, 선언과 동시에 누군가를 참조해야 한다.
  • 미리 참조자를 선언했다가 나중에 누군가를 참조하는 것은 불가능하며, 참조의 대상을 바꾸는 것도 불가능하다.
  • 참조자를 선언하고 NULL로 초기화 하는 것도 불가능하다.
  • 참조자는 무조건 선언과 동시에 변수를 참조하도록 해야 한다.
  • 배열에 대해 참조자 선언은 불가능 하지만 배열의 요소는 변수이므로 당연히 가능하다.

참조자(References)와 함수

참조자의 활용에는 함수가 큰 위치를 차지한다.

함수의 매개변수는 함수가 호출되어야 초기화가 진행되는 변수들이다. 다시 말해 함수 호출 시 전달되는 인자로 초기화를 하겠다는 의미이다. 따라서 함수의 인자로 참조자를 사용하는 것이 가능하다.

#include <iostream>

using namespace std;

void swap_by_ref(int &ref1, int &ref2)
{
    int temp = ref1;
    ref1 = ref2;
    ref2 = temp;
}

int main(void)
{
    int num1 = 10;
    int num2 = 20;
    swap_by_ref(num1, num2);
    cout << num1 << ", " << num2 << endl;

    return 0;
}

이렇듯 C++에는 Call-by-reference의 구현 방법으로 참조자를 이용하는 방법과 주소 값을 이용하는 방법이 존재한다.

함수 내에서 참조자를 통한 값의 변경을 진행하지 않을 경우 참조자를 const로 선언해서 함수의 원형만 봐도 값의 변경이 이뤄지지 않음을 보여야 한다.

void temp_func(const int &ref) { ... }

반환형이 참조형(Reference Type)인 경우

#include <iostream>

using namespace std;

int &func1(int &ref)
{
    ref++;
    return ref;
}

int main(void)
{
    int num1 = 1;
    int &num2 = func1(num1);

    num1++; // 3
    num2++; // 4

    cout << "num1: " << num1 << endl; // 4
    cout << "num2: " << num2 << endl; // 4

    return 0;
}

참조형으로 반환된 갑을 참조자에게 저장하면, 참조의 관계가 하나 더 추가된다.

func1의 매개변수로 선언된 참조자 ref는 지역변수이므로 함수를 벗어나면 소멸된다.

#include <iostream>

using namespace std;

int &func1(int &ref)
{
    ref++;
    return ref;
}

int main(void)
{
    int num1 = 1;
    int num2 = func1(num1); // num1과 num2는 별개의 변수이다

    num1 += 1;
    num2 += 100;

    cout << "num1: " << num1 << endl; // 3
    cout << "num2: " << num2 << endl; // 102

    return 0;
}

함수의 호출을 통해 다음의 과정이 진행되었다.

int num1 = 1;
int &ref1 = num1; // 인자 전달 과정에서 일어난 일
int num2 = ref; // 함수의 반환과 반환 값 저장에서 일어난 일

함수의 반환형이 참조형인 경우, 반환 값을 무엇으로 저장하느냐에 따라 그 결과가 차이가 있으므로, 적절한 선택을 해야 한다.

반환형이 참조형인 함수는 참조형과 기본형 두 가지 형태로 저장할 수 있다.

반환형이 기본형인 함수는 참조형에 저장이 안되고, 반드시 변수에 저장해야 한다.

잘못된 참조자의 반환

int& func1(int n)
{
	int num = 20;
	num += n;
	return num; // 지역변수 반환
}

위의 경우 지역변수 num에 ref라는 또 하나의 이름이 붙게 된다.

함수가 반환되면, 지역변수 num은 소멸되기 때문에 위와 같이 지역변수를 참조형으로 반환하면 안된다.

상수화 된 변수에 대한 참조자 선언

const int num = 20;
const int &ref = num; // 상수화 된 변수에 대한 참조자 선언

다음과 같이 상수도 참조가 가능하다.

const int &ref = 50;

C++에서는 위의 문장이 성립할 수 있도록, const 참조자를 이용해서 상수를 참조할 때 임시변수 라는 것을 만든다.

int Adder(const int &num1, const int &num2)
{
	return num1 + num2;
}

new & delete

#include <iostream>
#include <string.h>

using namespace std;

char *make_str_adr(int len)
{
    char *str = new char[len];
    return str;
}

int main(void)
{
    char *str = make_str_adr(20);
    strcpy(str, "Hello, world!");

    cout << str << endl;

    delete[] str;

    return 0;
}

C++에서는 mallocfree 대신 newdelete를 이용해 동적할당을 할 수 있다.

#include <iostream>
#include <stdlib.h>

using namespace std;

class Simple
{
public:
    Simple()
    {
        cout << "Simple Constructor!" << endl;
    }
};

int main(void)
{
    Simple *sp = new Simple;

    delete sp;
    return 0;
}

객체 생성 시에는 반드시 newdelete를 사용해줘야 하는데 그래야 생성자가 호출되기 때문이다.

C++에서 C 언어 표준 함수 호출하기

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>

.h를 생략하고 앞에 c를 붙이면 C 언어에 대응하는 C++ 헤더파일 이름이 된다.

참고 자료

  • 열혈 C++ 프로그래밍

좋은 웹페이지 즐겨찾기