[C++] 1. C언어 기반의 C++(1)


문자열 “Hello World”의 출력



항상 새로운 언어를 배울 때는 Hello World부터 출력해보죠~~

다음과 같이 출력합니다.

#include <iostream>

int main(void)
{
	int num=20;
	
	std::cout<<"Hello World!"<<std::endl;
	
	std::cout<<"Hello"<<"World!"<<std::endl;
	
	std::cout<<num<' '<'A';
	
	std::cout<<' '<<3.14<<std::endl;
	
	return 0;
}



C언어하고는 좀 많이 다르죠~!

눈에 띄는 성질이 3가지 있습니다.


1. 표준 헤더파일 선언 방식이 #include<stdio.h>에서

#include<iostream>으로 바뀌였습니다~!

그리고 C++에서는 프로그래머가 정의하는 헤더파일의 선언이 아닌,

표준 헤더파일의 선언에서는 확장자 .h를 생략합니다.



2. 출력을 위해서는 다음의 형태를 취합니다.

std::cout<< '출력대상';

그리고 '출력 대상'의 위치에는 정수, 실수, 문자열, 변수 모두 올 수 있습니다.

C에서처럼 출력대상마다 서식문자(%d,%s)를 이용할 필요가 없는거죠!



3. <<을 이용해서 출력대상을 연이어 출력할 수 있습니다.

std::cout<<'출력 대상 1'<<'출력 대상 2';

또 개행을 할 때는 다음과 같이 입력합니다.

std::cout<<std::endl;



확실히 C와 비교하여 출력 방법이 간편해진 걸 볼 수 있습니다~!

scanf를 대신하는 데이터의 입력



C++에서 키보드로부터 입력을 받는 방법은 다음과 같습니다

#include <iostream>

int main(void)
{
	int val1;
	
	std::cout<<"첫 번째 숫자입력:";
	
	std::cin>>val1;
	
	int val2;
	
	std::cout<<"두 번째 숫자입력:";
	
	std::cin>>val2;
	
	return 0;
	
}



위의 예제로부터 또 알 수 있는 성질이 2개 있습니다!


1. 데이터 입력을 위해서는 다음의 형식을 취하면 됩니다.

std::cin>>'변수';

변수는 자료형에 상관없이 올 수 있습니다.

심지어 문자열을 입력 받을 때도 

	char str[100];
	std::cin>>str;

라고 입력하면 됩니다~!

C++에서는 데이터의 입력도 데이터의 출력과 마찬가지로 서식문자를 이용하지 않아도 되는거죠!

연속적인 입력을 받을 때는 다음과 같습니다

	int num1,num2;
	std::cin>>num1>>num2;
	
정말 간편합니다~!


2. 그리고 C++에서는 지역변수를 함수를 정의할 때 맨 윗부분에 선언 안 해도 됩니다!

어디서든 변수를 선언해도 컴파일 에러가 발생하지 않죠~! 정말 좋습니다



함수 오버로딩



C언어에서는 다음과 같이 동일한 이름의 함수가 정의되는 것을 허용하지 않습니다.

int fun(int num)
{
	num++;
    retrun num;
}

int fun(int num1,int num2)
{
	return num1+num2;
}



그 이유는 C언어는 함수의 이름만 이용해서 호출대상을 찾기 때문입니다.

하지만, 함수의 이름과 매개변수의 선언을 이용하여 호출대상을 찾는 C++에서는,

위의 코드를 문법적으로 허용합니다.

이와 같이 함수의 이름이 같을 때, 전달되는 인자를 통해서 함수를 구분하는 방법을

‘함수 오버로딩’이라고 합니다.



매개변수의 디폴트 값



앞서 함수 오버로딩에 대해 언급하였는데, C++의 함수에는 디폴트 값이라는 것을 설정할 수 있습니다.

int function(int num=7)
{
	return num+1;
}



위와 같이 매개변수에 디폴트 값이 설정되어 있으면,

다음 선언은 동일한 표현이 됩니다!


function(); //함수호출 시 인자를 전달하지 않으면 디폴트 값으로 전달

function(7);



또, 매개변수가 여럿일 때도 디폴트 값을 설정가능합니다.

하지만 주의해야할 것이 디폴트 값을 설정 안 할 때는 왼쪽부터 차례대로 비워야합니다!


int function(int num1=1,int num2=2, int num3=3); (O)

function(5); 는 function(5,2,3)과 같습니다.

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


int function(int num1, int num2=2, int num3=3); (O)

int function(int num1, int num2, int num3=3); (O)

int function(int num=1,int num2, int num3=3); (X)

왼쪽 매개변수의 디폴트 값이 설정되어있으면 나머지도 설정되어야합니다. 




그리고 디폴트 값은 함수의 원형말고 선언 부분에만 표현하면 됩니다!



마지막으로 다음과 같은 함수 오버로딩은 문제가 있습니다.


int function(int a=10)
{
	return a+1;
}

int function(void)
{
	return 10;
}



왜냐하면 function()라고 선언 시 둘 중 어떤 함수를 호출한 것인지 모르기 때문입니다.



인라인(inline) 함수



C언어에서 공부한 매크로 함수 기억하시나요??

#define SQUARE(X) ((X)*(X))



매크로함수는 일반적인 함수에 비해서 실행속도가 빠르다는 장점이 있지만,

정의하기 어렵고, 복잡하다는 한계가 있다는 단점이 있었습니다.

매크로 함수는 컴파일전에 전처리기위해서 단순 치환되는 형태였죠!

매크로함수의 장점은 유지하되, 일반 함수처럼 정의하였으면 좋겠다는 생각이 드실텐데요~

C++에서는 그 요구를 충족시키는 인라인 함수가 존재합니다!

선언방식은 다음과 같습니다


inline int SQUARE(int x)
{
	return x*x;
}



하지만 인라인 함수는 매크로 함수와 다르게 전처리기가 아닌 컴파일러에 의해 처리가 되서,

컴파일러가 함수의 인라인화가 오히려 성능에 해가 된다고 판단하면 이를 무시할 때도 있습니다.

또 매크로 함수는 자료형에 상관없이 인자로 전달 받을 수 있지만,

인라인 함수는 그렇지 못합니다.

이를 해결해주는게 나중에 배울 템플릿인데 일단 패스하겠습니닼ㅋㅋ

일단 인라인 함수가 있다는 걸 기억해주시길 바랍니다~!



이름공간(namespace)



프로그램이 대형화가 되어 가면서 이름의 충돌문제가 등장하였는데요~

예를 들어 여러명이 한 프로그램을 따로 작성하고 합칠 때 함수의 이름이 같다면,

많은 문제가 발생합니다!

이를 해결해주는 것이 namespace입니다!

방식은 다음과 같습니다.

#include <iostream>

namespace A
{
	void function(void)
	{
		std::cout<<'A'<<std::endl;
	}
}

namespace B
{
	void function(void)
	{
		std::cout<<'B'<<std::endl;
	}
}



위와 같이 함수이름이 같아도 다른 namespace라면 충돌이 발생하지 않습니다.

호출은 다음과 같이 하면 됩니다.

int main(void)
{
	A::function();
	
	B::function();
	
	return 0;
}

//여기서 ::는 범위지정 연산자라 하며 이름공간을 지정할 때 사용하는 연산자입니다.



또 이름공간은 다른 이름공간 안에 삽입될 수 있습니다.


namespace A
{
	namespace B
	{
		void function(void)
		{	
			std::cout<<'AB'<<std::endl;
		}
	}
}



접근할 때는 다음과 같이 하면 됩니다.

A::B::function();



using을 이용한 이름공간의 명시



namespace A
{
	void function(void)
	{
		std::cout<<'A';
	}
}



namespace A 안에 선언된 함수에 접근할 때,

항상 A:: 라는 걸 앞에 붙여야합니다.

입출력 할 때도 std:: 을 붙여야 하구요!!

정말 귀찮은 작업이죠~ using을 사용하면 해결할 수 있습니다.


using A::function; 

위와 같이 선언하면 앞으로 function을 선언할 때 A::을 안 붙여줘도 됩니다!


또, namespace에 있는 모든 함수에 적용시키고 싶으면,

using namespace A;

라고 하면 됩니다!



using을 입출력함수도 편리해집니다!


#include <iostream>
using namespace std;

int main(void)
{
	cout<<"Hello"<<endl;
	
	return 0;
}