반응형

"C++이 무엇인가요?" 라는 질문에 대한 답변은 다양하게 나올 수 있을 것이다.

그러한 답변들 중에 하나가 "C++ is a c with class."이다.

 

 이는 C++은 C에 Class에 관한 사항이 추가되었다는 것이다. 물론, C++에 대한 답변으로 부족하다고 할 수 있을 것이다. 다만, C++ 언어를 배움에 있어 Class에 초점을 둘 필요성이 있다는 말로 받아들인다면 충분히 의미가 있을 것이다.  앞으로 C++ 언어에서 Class에 관한 사항은 하나씩 살펴보기로 할 것이다.

 

이 글에서는 C++의 클래스에 대해 소개하기 전에 Class를 제외한 부분에서 C언어와 다소 차이가 있는 부분을 다루고자 한다.

 

먼저, C++은 C언어에 비해 신뢰성을 강화시킨 언어이다. 이는 개발자의 잘못될 수 있는 코드를 컴파일러가 예측하여 에러를 통보함으로써 이에 대해 개발 단계에서 수정할 수 있게 함으로써 이루어진다. (물론, C#이나 Java에 비하면 신뢰성 보다는 유연성이 있다고 보는 것이 맞을 것이다.)

 

 - 열거형과 정수형과의 관계

 C언어에서는 열거형은 정수형과 묵시적 형변환이 이루어졌고 이는 단순히 상수들을 그룹화하는 정도의 특징을 지녔다. C++에서는 열거형 값이 와야 하는 곳에 정수형이 사용될 때 열거형에 나열한 값의 범위를 벗어날 개연성이 있기 때문에 error를 발생시킨다. 물론, 정수형이 와야 하는 곳에 열거형이 사용될 때에는 정수형을 벗어날 개연성이 없기 때문에 아무런 문제가 되지 않는다.

 


 - const 포인터와  포인터와의 관계

 함수의 매개 변수중에 포인터 형의 경우 피 호출 함수에서 해당 주소의 값을 변경하지 않음을 명시하기 위해 const 포인터를 사용하여 신뢰성을 높이는 경우가 있다. 이 경우 C언어에서는 const 포인터 형식의 변수로 간접 연산을 통해 값을 바꿀 경우 경고를 하였지만(컴파일 경고 수준을 변경하지 않는다는 가정) C++에서는 에러를 발생함으로써 개발자가 비 신뢰적인 코드를 작성하는 것을 개발 단계에서 방지할 수 있다.

 


 

 - void 포인터와 포인터와의 관계

void 포인터 형의 변수는 선언 시에 원소 형식을 명시하지 않는 포인터 형식의 변수로 어떠한 형식의 포인터 값도 받을 수 있다. 하지만, void 포인터 형의 변수를 일반(void 포인터 형이 아닌) 포인터 변수에 대입을 할 경우 신뢰성이 위배될 개연성이 있기 때문에 C++에서는 이 경우에도 경고 수준이 아닌 에러를 발생하여 개발 단계에서 신뢰성이 있는 코드를 작성할 수 있게 된다. 특히, void 포인터 형의 변수에 int형 포인터 변수의 값을 갖고 있다고 하더라도 int형 포인터 변수에 대입하는 경우에도 에러를 발생한다. 그러한 이유는 해당 변수에 어떠한 값이 있는가에 대한 판단은 런 타임 시에 할 수 있는 것이고 컴파일 시에는 타입에 의거하여 판단을 한다.

 


 

 - bool 형식의 제공

 프로그래밍을 하다보면 특정 연산 결과가 참인지 거짓인지를 판별해야 하는 경우가 있는데 이와 같이 참과 거짓을 값으로 지닐 수 있는 형식으로 C++에서는 bool 형식을 제공하고 있다. bool 형식에는 참에 해당하는 true와 거짓에 해당하는 false를 값으로 가질 수 있다. 이를 통해 프로그램의 논리적 신뢰성을 좀 더 높일 수 있다고 본다.

 void main()

 {

     bool check = false;

     check = IsEventNumber(37);

     if(check)

     {

          ...중략...

     }

     else

     {

          ...중략...

     }

 }

 

 

 bool IsEvenNumber(int num)

 {

    return (num%2)==0;

 }

 

enum Gendor
{
    FEMALE,
    MALE
};

void ExampleEnumVSInt();
void ExampleConstVsNonConst();
void ExampleVoidPointerVSPointer();
void main()
{
    ExampleVoidPointerVSPointer();

}

void ExampleVoidPointerVSPointer()
{
    int i = 3;
    int *pi = &i;
    void *pv = &i;

    //pi = pv;
    pv = pi; 
}

void Foo(const char *str);
void ExampleConstVsNonConst()
{
    char arr[10]="hello";

    Foo(arr);
}

void Foo(const char *str)
{
    //char *p = str;
    //*p='a';
}

void ExampleEnumVSInt()
{
    Gendor g=FEMALE;
    int i=0;

    //g = i;
    i = g;
}

 

C++에서는 신뢰성에 문제가 되지 않는 범위에서 개발자의 편의성을 제공하는 부분도 많이 있다.

 

 - 태그명이 형식명으로 사용이 가능하다.

 C언어에서는 struct Stu stu;와 같이 struct(union,enum)와 같은 키워드와 태그명을 명시해야 형식명으로 사용이 가능하였는데 C++에서는 Stu stu;와 같이 태그명이 형식명으로 사용이 가능하다.

 

 - 함수 중복 정의

  C++에서는 동일한 이름을 갖는 함수를 중복 정의할 수 있다. 이는 C++ 컴파일 과정에서의 전개가 이루어지는 동안 개발자가 정한 함수명을 매개변수 인자에 따라 유일한 이름으로 함수 부호화(코드화) 과정이 진행되고 호출 부분은 부호화된 적절한 함수 호출로 연결(함수 Name Mangling)이 이루어진다.  

 
 

int GetMax(int a,int b)   //함수 부호화 과정을 통해 유일한 이름으로 변경된다.

{

           if(a>b)

           {

                     return a;

           }

           return b;

}

char GetMax(char a,char b) //함수 부호화 과정을 통해 유일한 이름으로 변경된다.

{

           if(a>b)

           {

                     return a;

           }

           return b;

}

void main()

{

//부호화 과정을 통해 유일한 이름이 된 함수들 중에 인자가 가장 적절한 함수 호출로 번역된다.

           cout<<GetMax(2,3)<<endl;

//부호화 과정을 통해 유일한 이름이 된 함수들 중에 인자가 가장 적절한 함수 호출로 번역된다.

           cout<<GetMax('a','b')<<endl;

}

 

 함수 중복 정의는 결국 C++ 컴파일러의 전개과정에서 유일한 이름의 함수명으로 변경되고 호출부의 코드도 인자가 가장 적절한 함수로 연결되는 것이다. 즉, 모든 경우에 함수 중복 정의가 가능하지는 않다.
 



 

위의 예를 보면 두 개의 함수는 리턴 형식을 제외한 나머지 부분에서 모두 동일하다. 함수 호출부에서 리턴 값을 사용하는 것은 강제 조항이 아니기 때문에 리턴 형식만 다른 경우에는 함수 중복 정의가 불가하다.

 

 이 외에도 함수 호출부에 있는 코드를 어느 함수로 연결(함수 name mangling)할 지 판단하기 애매모한 경우에도 에러가 발생한다.

 


 

 - 디폴트 매개 변수

C++언어에서는 함수의 입력 매개 변수중에 대부분의 경우 동일한 인자 값을 사용을 할 경우 등에 사용할 수 있게 디폴트 매개 변수를 제공하고 있다.  

 
 

double CalculateArea(double radius, double radian=3.14)

{

           return radius*radius*radian;

}

 

void main()

{

           cout<<"반지름이3인원의넓이:";

           cout<<CalculateArea(3)<<endl;

           cout<<"반지름이3인반원의넓이:";

           cout<<CalculateArea(3,3.14/2)<<endl;

}


 

 위의 CalculateArea함수는 반지름과 부채꼴의 중심 각에 대한 radian을 인자로 받아 넓이를 구하는 함수이다. 두 번째 입력 매개 변수의 디폴트 매개 변수 값을 3.14로 지정함으로써 원의 넓이를 구할 경우에는 호출 시에 중심 각에 대한 radian을 인자로 넣지 않더라도 디폴트 값을 사용하게 된다. 물론, 특별한 인자 값을 전달하면 해당 값이 전달된다.

 

 - 매개 변수 명이 없는 입력 매개 변수 허용

 C++에서 함수 중복가 가능하다는 것은 위에서 이미 언급한 바가 있다. 그런데, 경우에 따라서 입력 인자가 동일한 경우에는 어떻게 할 것인가? 물론, 함수명을 다르게 주는 아주 쉬운 방법이 있다. 만약, 함수명을 다르게 주기를 원하지 않는다면 매개 변수명이 없는 입력 매개 변수를 사용하면 된다. 호출하는 곳에서는 호출하는 함수가 어느 것인지 구분하기 위해 의미는 없지만 값을 넣어주어야 하는 번거로움이 있기는 하다.

 

 

int CalculateArea(int width,int height)

{

           return width*height;

}

int CalculateArea(int width,int height,bool)

{

           return width*height/2;

}

 

void main()

{

           cout<<"사각형넓이:";

           cout<<CalculateArea(3,4)<<endl;

           cout<<"삼각형넓이:";

           cout<<CalculateArea(3,4,false)<<endl;

}


 

 - 기타

 또한, C++언어는 성장이 멈춘 상태로 있는 것이 아니라 성장을 계속하고 있는데 namespace와 같은 문법 사항이나 구조적인 예외 처리에 관한 부분은 C++언어가 태동한 이 후에 추가적으로 제공하는 문법 사항이다.

출처 :  http://blog.daum.net/ehclub

반응형

'프로그래밍 > Language C++' 카테고리의 다른 글

[C++]오버로딩 과 오버라이딩  (0) 2013.03.31
[C++] 연산자 오버로딩 연습  (0) 2012.05.30
[C++] 캡슐화 개요 샘플  (0) 2011.12.23
[C++] 캡슐화 개요  (0) 2011.11.16