삽질의 현장/- C++

#001_시(c)시(c)해서 C++!?... C와 C++의 차이

shovelman 2015. 7. 2. 01:03

오늘부터 C++에 대해서 알아보록 하겠습니다.


C++은 C언어의 문법에 새로운 것들이 추가된 언어입니다. 그래서 ++ 한거죠...


C와 C++의 가장 큰 차이라고 한다면,

바로 객체지향이라는 개념에 있지 않을까 합니다.


C++ 언어는 신뢰성에 관해 많은 문법적인 제약을 두어서 

신뢰성 없는 부분에 대해 오류를 발생하여 수정하게 합니다.

C에서는 warning 이었던 사항들이 error로 되어 아에 컴파일 진행이 못되게 하는 경우가 있다 이겁니다.


물론 이 비교는 C#이나 Java가 아닌 

오직 C언어와의 비교를 하는 것을 명심해주시길 바랍니다.


C++언어는 객체 중심으로 프로그래밍을 할 수 있는 특징을 가지고 있습니다.

영어로 Object Oriented Programming Language 라고 하죠... 푸하하

줄여서 OOP의 중요한 특징으로는 캡슐화, 상속, 다형성을 들 수 있다고 합니다.


이부분에 대해서는 후에 차근차근(?) 알아가 보도록 하겠습니다.


C++과 C언어에서 다른 문법 사항들을 몇가지 알아보려 합니다.

(클래스 부분은 나중에 정리해보도록 하겠습니다)


.cpp 파일에서도 C언어의 기능을 그대로 사용할 수 있는 것은 아시죠?

그렇다고 다 똑같지는 않겠죠.... 서로 다른 부분들에 대해서 지금부터 알아보겠습니다.


첫번째로 C++ 언어에서는 사용자의 논리적 오류에 대해서 

C에 비해 더 빡시게... 검사하기 떄문에 신뢰성이 높아졌다고 말씀드릴 수 있을 것 같습니다.


신뢰성에 대한 예제 코드를 보고 가시겠습니다.

열거형 예시입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum Sports
{
    FOOTBALL, BASEBALL
};
 
void main()
{
    int sInfo1 = 0;
    enum Sports sInfo2 = FOOTBALL;
 
    // 정수 값 대입에 문제 없다.
    sInfo1 = sInfo2;
    sInfo2 = sInfo1;
 
    //C++에서 에러. C보다 신뢰성을 요구한다. 
    sInfo2 = 9;
}
cs


또한 bool 형식을 C++에서는 제공하게 됩니다...

즉, C에서 참이면 0이외에 정수를, 거짓이면 0을 반환하는 코드를 여러번 작성 해보셨죠?

이와 같은 기능을 C++에서는 bool 이라는 형식을 제공함으로써 보다 가독성을 높여줄 수 있죠...


두번째로, C++언어에서는 편의성을 제공해줍니다.


우리 C언어로 구조체 선언할 때 이름 길어서 typedef를 통해 별칭을 지었었는데... 

C++서는 태그 명이 형식 명으로 사용할 수 있다 이겁니다... 


1
2
3
4
5
6
7
8
9
10
struct Soccer
{
   int goals;
   char name;
};
 
void main()
{
    Soccer Sap = {3"삽잡이"};
}
cs


이렇게 말입니다... 오우 삽잡이 군이 3골이나 넣었군요... 죄송합니다 멍멍 소리 입니다...


또한, 원하는 위치에 변수를 선언할 수 있습니다.

기존의 C언어에서는 블럭( { )이 시작함과 함게 변수들을 모두 선언해줘야 했습니다...

중간에 위치하면 에러를 냈죠...

하지만 C++ 에서는 필요에 맞도록 중간에 오는 것을 허용해줍니다.


많이들 보시는 예시가 있죠... C에서는 안되는 그 for문 예시..


1
2
3
for(int i = 0; i<3++i)
{
}
cs


이렇게 사용할 수 있다 이겁니다...


C와는 다르게 레퍼런스 변수라는 것도 사용할 수 있습니다.

레퍼런스... 참조? 음... 용량없는 변수에요... 

하지만 레퍼런스 변수는 주소값을 공유하는 변수인데요... 말을 어렵게 했죠? 하하..

다음에 다시 자세하게 언급할 기회가 있을 것입니다!



다음으로 정말 중요한 함수 중복 정의입니다.

C++에서는 동일한 함수 명을 중복하게 정의할 수 있다는 것이죠...

C에서는 상상도 못했을... 바로 OverLoading, 오버로딩이라고 부릅니다..


C++ 에서는 함수의 시그니처만 다르다면 같은 의미의 함수를 정의하 수 있습니다.

예를 들어서 도형의 면적을 구하는 함수가 있다고 생각해봅시다.


그렇다면 이렇게 예시를 들어보도록 하죠...


1
2
3
4
5
6
7
8
9
10
//사각형의 면적 구할 때.
double CalArea(double height, double width)
{
    return height * width;
}
//원의 면적 구할 때.
double CalArea(double radian)
{
    return radian*radian*3.14;
}
cs


아까 언급한 것과 같이 

함수의 시그니처가 다른 동일한 함수명이 중복으로 정의 되어있습니다.

C++에서는 컴파일러가 컴파일을 하면서 동일한 함수명일지라도, 

매개 변수의 목록을 보고 판단한 뒤 독립적인(같지않은) 함수명으로 변경해버립니다.


즉, 사용자가 정의한 함수명을 

매개 변수 리스트에 따라 유일한 이름의 함수명으로 결정하는 

함수 부호화(코드화) 과정이 진행된다 이겁니다.


그리고 C++에서는 함수를 메서드라고 부른다죠... 

아무튼... 다시 말씀드리자면, 함수 중복 정의는 결국 C++ 컴파일러가 

겹치지 않는 함수명으로 변경하게 되고, 


우리가 작성한 코드에서 동일한 이름의 메서드를 호출할때 

매개변수를 보고 판단하여 함수로 연결 시켜준다는 것이죠...


C++에서는 참 C에 비해 

간단하고 편리하게 사용할 수 있는 기능들을 제공해주는거 같아요? ㅎㅎ

지금은 C++을 배우고 있으니 C가 아닌 C++에 관심과 사랑을... 푸하하...


그렇다고 이것들만 제공하는 것은 아니겠죠...

바로 디폴트 매개 변수도 제공한답니다.


특정 함수를 호출할 때 사용하는 입력 매개 변수의 값이 같을 경우 애초에 때려박고 가는 것이죠...


1
2
3
double CalArea(double radian, double radius=3.14)
{
}
cs

이렇게 사용할 수 있다 이겁니다... 

또 이런 경우가 있을 수 있습니다... 동일한 메서드명을 써야되는데... 인자도 같네... 

그럼 못쓸까요? 아닙니다...

C++ 에서는 스텁 매개변수라고 그냥 형식만 던져주는 매개변수를 선언해줄 수 있습니다.


그말은 뭐냐... 예제를 보시죠...


1
2
3
4
5
6
7
8
9
double CalArea(double height, double width)
{
    return height * width;
}
//스텁 매개 변수
double CalArea(double height, double width, int)
{
    reutnr height * width /2;
}
cs

이렇게 말입니다... 메서드 명이 동일한데 매개변수에 그냥 int 형식 하나 때려박았죠...

물론, 호출할 때 사용은 안하겠지만 인자로는 하나를 넘겨줘야합니다.

안넘겨주면 어떻게 또 구분해요 ㅎㅎ



C/C++ 은 만들어진지 좀 됬죠? 물론 더 오래된 언어들도 있겟지만...

그런데요, 우리는 우리가 모든 함수를 직접 만들고 사용하는 것은 아니죠...

라이브러리를 가져와 사용할 때가 있습니다.

그래서 C언어에서 보면 stdio, string, stdlib 등등과 같이 여러 라이브러리들을

가져다가 사용할 수 있습니다.


그런데말입니다... 라이브러리는 수도없이 많을터인데

여러 라이브러리들을 사용하다가 혹여나 똑같은 이름의 형식이나 객체등이 정의 되어있다면

어떻게 될까요... 그 라이브러리는 사용할 수 없겠죠... 왜냐 ... 구분을 못하니까요...


이때 사용하는 것이 namespace 입니다...

같은 이름의 형식이나 객체 등이 정의된 여러라이브러리 들 중에서 원하는 부분을

사용할 수 있도록 해주는...


예시를 보시죠...


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//삽 회사의 라이브러리
namespace SLib
{
 
    struct Stack
    {
        int base[10];
        int top;
    };
 
    struct Queue
    {
        int base[10];
        int top;
        int front;
    };
}
 
//잡이 회사의 라이브러리
namespace ZLib
{
    struct Stack
    {
        int buffer[100];
        int top;
    };
    struct Queue
    {
        int buffer[100];
        int top;
        int rear;
    };
}
cs


이와 같이 똑같다면... 


1
2
using namespace SLib;
using namespace ZLib;
cs


이렇게 사용한다면 되겠죠... 그런데 문제가 있습니다... 둘다 저렇게 쓰면 또 충돌 날 터인데...

이럴때는 스코프 연산자( :: )를 사용하여 

서로 다른 라이브러리에 같은 이름의 라이브러리 중 원하는 것을 골라 사용할 수 있게됩니다.


1
2
using SLib :: Stack;
using ZLib :: Queue;
cs


이렇게 사용할 수 있다 이겁니다...