본문 바로가기
Basic/C/C++

[C++ 언어] 제 1 강 : 기본적인 C++

by boxbop 2012. 2. 1.
반응형


 C언어에 바로 이어서 C++언어로 넘어왔습니다. C언어 학습 후에 공부하게 되는 C++이므로 C언어에서 다루지 않았던 추가적인 내용들, 또는 C언어와 C++언어의 차이점 등에 중점을 두고 공부할 생각입니다. C++언어는 C언어를 포함하고 있습니다. 즉, C++은 C언어가 지니지 않는 문법적 특성도 많이 가지고 있다는 이야기입니다. 참고로 C++언어의 확장자는 .c 가 아닌 .cpp 로, 헤더파일은 #include<stdio.h>가 아닌 #include<iostream>으로 지정해 줘야 되는거 잊지마세요~~

 
cout << 출력대상
 cout<<1<<'a<<"string"<<endl;

: C언어의 printf 함수는 출력하고자 하는 대상의 출력 포맷을 정의해줘야 했지만 C++의 이러한 출력 방식은 우리가 원하는 형태로 적절히 출력을 해줍니다. endl을 출력하라는 의미는 다음 줄로 넘어가라는 의미를 가지고 있습니다.

 #include <iostream>

 int main(void)
 {
    std::cout<< "hello boxbop!!"<<std::endl;
    return 0;
  }

 std:: 나 << 연산자는 곧 설명할테니 조금만 기다려주시구요~

 
cin >> 입력 변수
 cin >> value;
 cin >> value1 >> value2;

:cout을 이용한 출력이 자료형에 맞는 적절한 출력을 보장했던 것처럼, cin을 이용한 데이터의 입력은 자료형에 맞는 적절한 입력을 보장해주고 있습니다~또한!!!!!! 중요한 것중에 하나는 C++는 원하는 위치어디서나 변수를 선언하는 것이 가능합니다!! C언어에서는 함수를 정의함에 있어서 지역 변수의 선언이 항상!! 제일 먼저 등장해야 했습니다!! 이에비하면 엄청나게 편한거죠~
그리고 첫 번째 데이터와 두 번째 데이터의 경계는 탭, 스페이스바, 엔터키의 입력에 의해 나눠집니다. C언어의 scanf함수와 동일하죠~

 #include <iostream>

 int main(void)
{
   int value1, value2;

   std::cin>>value1>>value2;
   std::cout<<"입력 값: "<<value1<<','<<value2<<endl;
   return 0;
 }

 
함수의 오버로딩?!

C컴파일러는 호출하고자 하는 함수를 찾을 때 오로지 함수의 이름 정보만을 가지고 찾기 때문에 정의된 매개 변수의 형태가 달라도 동일한 이름의 함수 정의는 허용되지 않습니다. 그러나 C++는 가능합니다. 왜냐하면 함수의 이름뿐 아니라 매개 변수의 정보까지도 참조를 하기 때문이죠~ C++은 이름이 같고 매개 변수의 타입 혹은 개수가 다른 함수들의 정의를 허용합니다. 이를 함수 오버로딩(function overloading)이라고 합니다.

 int function(int n)
 int function(char c)
 int function(int v1, int v2)

위 의 3개의 함수는 모두 다른 함수입니다. 함수의 이름은 같지만 매개 변수의 타입 및 개수가 다르기 때문입니다. 다만 함수의 리턴 타입만 다르다고 해서는 함수가 오버로딩되지는 않습니다^-^

 디폴트 매개 변수

디폴트(Default) 즉, 기본적인 매개 변수라는 것이 C++에서는 존재합니다.

int function(int a=0)
{
    return a;
 }

 현재 매개 변수 a는 0이라는 디폴트 매개 변수 값이 설정되어 있습니다. 이 값이 의미하는 것은 function이라는 이름의 함수를 호출하면서 인자를 전달하지 않으면 0으로 간주하겠다!!입니다. 말 그대로 기본 설정 매개 변수입니다~
 즉, function()function(0)은 동일합니다. 여기서 한 가지 주의할 것은 함수의 선언이 함수의 정의 이전에 존재하는 경우 디폴트 매개 변수는 선언 부분에 놓여져야 합니다.

 인라인(in-line)함수
C언어에서 배웠던 매크로가 기억나시나요? 함수를 매크로로 정의하면 전처리기에 의해서 함수 호출 문장이 함수의 몸체 부분으로 완전히 대치돼 버립니다. 함수의 호출 과정이 사라졌기 때문에 성능적인 면에서도 뛰어나죠. 함수 호출 문장이 함수의 몸체 부분으로 완전히 대치되 버리는 현상을 가리켜 함수가 inline화 되었다고 표현합니다.

 #include <iostream>
 inline  int  function(int x)
 {
    return x*x;
 }

 int main(void)
{
   std::cout<<function(5)<<std::endl;
}
 
 함수 function을 inline화 하게 됩니다. function(5)는 (5 * 5)로 단순히 치환됩니다. C++에서는 이와 같이 성능 향상을 목적으로 함수를 inline화하기 위해서 매크로를 사용할 필요가 없습니다.

 이름공간(namespace)
이름공간은 말 그대로 특정 영역에 이름을 붙여주기 위한 문법적 요소입니다. 예를들어 A회사와 B회사가 공동으로 프로젝트를 진행한다고 합시다. 몇 달후에 각각의 회사가 구현한 모듈을 하나로 묶기 위해서 모였습니다. 그러나 A회사와 B회사가 각각 구현한 함수들의 이름이 같은 경우가 일어났습니다. 이는 상당히 골치아픈 문제입니다. 만약 이런 경우라면 어떻게 해야 될 까요? 한 아파트에 민식이라는 친구가 2명 살고 있습니다. 202호 민식이와 702호 민식이죠 아파트 방송에서 민식이라는 친구를 부를 때 그냥 민식이라고 하면 202호 민식이 인지 704호 민식이인지를 모를겁니다. 때문에 202호 민식이나, 702호 민식이라고 불러야되는거죠. 즉, 같은 이름을 가졌더라도 존재하는 공간을 다르게해서 구분짓도록 합니다.

 #include <iostream>

 namespace A_company
 {
    void function(void)
    {
        std::cout<<"A회사에서 정의한 함수"<<enld;
     }
  }

 namespace B_company
 {
    void function(void)
    {
        std::cout<<"B회사에서 정의한 함수"<<enld;
     }
  }

int main(void)
{
    A_company::function();
    B_company::function();
 }

 namespace라는 키워드로 이름 공간을 구성하고 내부에 필요한 함수들을 정의 합니다. A회사의 이름공간에도 function함수가, B회사의 이름공간에도 function함수라는 똑같은 이름을 가진 함수가 존재합니다. 이름공간이 다르다면 같은 이름의 변수나 함수의 선언이 허용되기때문에 가능한 일입니다. 중요한 것은 이름공간 내에 선언되어 있는 변수나 함수에 접근하는 방법입니다.
:: 연산자가 보이시나요? 이 연산자를 범위 지정 연산자라고 합니다. 
 A_company::function() 에서 의미하는 것은 A_company라는 이름공간 안에 선언되어 있는 function함수를 호출하라는 의미입니다. 

 함수의 선언과 정의를 분리하고자 하는 경우에는 다음과 같이 하셔야됩니다.

#include <iostream>
namespace A_company 
//함수의 선언
{
   void function(void)
 }
namespace B_company
{
   void function(void)
 }

int main(void)
{
    ......
//메인함수의구현
 }

namespace A_company
//함수의 구현
{
      void function(void)
      {
           std::cout<<"A회사 함수"<<endl;
       }
 }
namespace B_company
{
      void function(void)
      {
           std::cout<<"B회사 함수"<<endl;
       }
 }

 자 그렇다면 우리가 지금까지 사용해온 std::cout 나 std::endl 또는 std::cin을 이해할 수 있겠죠? std라는 이름공간안에 존재하는 함수들을 사용하겠다는 의미가 됩니다.

   using 이라는 키워드
 cout, cin, endl을 참조할 때마다 std:: 를 앞에다 붙여줘야 하는 이유는 설명했습니다. 그렇다면 항상 이렇게 붙여서 사용해야 되는 것일까요? 이를 해결하기위한 방법이 있습니다.

#include <iostream>

 namespace A
{
    void funtion(void)
    {
        std::cout<<"hi! boxbop"<<endl;
     }
 }

 
using A::function;

int main(void)
{
    function();
    return 0;


 using A::function 와 같은 선언은 앞으로 function이라는 이름을참조하는 코드가 나오면 A라는 이름공간 안에 선언된 function이라는 이름을 참조하라는 의미입니다. 

 using std::cout;
 using std::cin;
 using std::endl;

 이렇게 코드를 작성하면 메인함수에서는 일일히 std::를 안붙여주고 cout, cin, endl을 사용할 수 있습니다.

 using namespace std;

라고 작성하면 어떻게 될까요? 이것은 이름공간 std안에 존재하는 이름들은 그냥 참조하겠다고 선언되어 있는 것 입니다. 따라서 이후부터는 범위지정 연산 없이 접근이 가능하게 되는 것이죠. 그러나 이와 같은 선언은 나중에 충돌을 일으킬 수 있는 원인이 될 수 있어서 using std::cout 와 같이 조금은 번거로워도 일일이 작성해주는 편이 좀 더 좋습니다.(일일히는 일일이의 옛말이더군요..... 갑자기 헷갈려서 찾아봤습니다. 참고~)

 int value = 100; // 전연변수

int main(void)
{
   int value = 100;  //지역변수
   ::value += 1;  //전역변수
   return 0;
 }

::value += 1; 에서 범위 지정 연산자를 사용해서 전역변수에 접근을 하고 있습니다. 그러나 이름공간이 따로 존재하지 않는데요 이는 전역 변수로 선언되어있는 변수 value에 접근하라는 뜻이 됩니다. 때문에 범위 지정 연선자는 전역 변수에 접근하기 위한 용도로도 사용이 가능합니다.

 오늘은 여기까지 하도록 하겠습니다. 다음 장에서는 본격적으로 C++에 들어가기에 앞서서 레퍼런스에 대한 내용을 좀 더 살펴보도록 하겠습니다~
 
 
 

반응형