본문 바로가기

Computerscience/C#

C#과 C++ 문법적으로 다른점

C++과 문법적으로 다른점

 여기서는 C++과 C#의 차이점을 간단히 설명할 것이다. 여기서 다른점 모든 것을 설명하는 것은 아니고 기본 문법 요약 정도로 생각하면 될듯하다. 여기서 설명하는 내용은 C++과 다른점이지 C++ .NET과 다른점이라고 생각하면 안된다.

1. Header 파일이 존재하지 않는다.

C++에서 Class 선언을 Header(.h)에 하고 #include를 사용하여 그 Header 파일을 포함 시킴에 의해 .cpp파일의 Class를 사용하도록 한다. 그러나 C#은 .cs 파일만으로 구성된다. 실제 C++에서 Header파일은 형선언을 하여 그 Class를 사용한다고 컴파일러에게 알려주는 역할을 수행한다. 이 부분을 하기 위해서 Header 파일을 만드는 일도 약간이나마 번거러운 일이다. C#은 같은 프로젝트에 .cs로 존재하거나 다른 어셈블리(.exe, .dll)일 경우 참조(향후 설명)만 하면 자동으로 인식하여 컴파일을 하게된다.

 

2. Namespace라는 개념이 추가 되었다.

Namespace는 Class를 감싸는 대표이름이라고 생각하면 된다. 여러개의 Class를 제작하여 하나의 대표이름을 붙여 놓은 것이 namespace다. 이것은 같은 이름의 Class를 여러개 만들수 있도록 하는데, 같은 이름의 Class가 다른 namespace에 존재하면 구분이 가능하게 된다.

여기서 설명의 편의상 Class라고 했으나 Class는 Type의 대표적 종류이다.

Type
- Struct
- Enum
- Class
- Interface
- Delegate

Delegate만 제외하면 모두 C++에도 있는 개념이다. Delegate는 Event와 쌍으로 사용하는데 C# 문법에서 가장 중요한 개념이다. 자세한 설명은 두 번째 강의에서 설명하도록 하겠다.

참고로 Struct와 Class는 C#에서 거의 같은 기능을 수행한다. Struct도 Method(함수), Property(변수)등 모든 Member를 가질 수 있다. 다만 Class는 상속이 가능하고 Struct는 불가능하다는 것만 다르다. 이 두가지의 차이는 만들때의 목적을 생각하면 기억하기 좋다. Struct는 빠른 데이터 처리를 위해 만들어 졌고, Class는 다양한 가지 기능을 가질수 있도록 만들어 졌다. 상속은 속도는 저하되나 다양한 기능을 지원할 수 있도록 한다.

Member
- Field
- Method
- Property
- Event

여기서도 Event만 제외하면 모두 C++에 있는 개념이다.

 

3. using

위에서 설명한 바대로 namespace라는 개념이 추가되어 같은 이름의 Type을 여러개 작성할 수 있도록 되었다. 그러나 이개념에 의해 Method하나 호출하기 위해 Namespace.Type.Method의 형태로 호출해야만한다.

즉 MessageBox하나 호출하기 위해 System.Windows.Forms.MessageBox.Show("Hellow World")라고 호출해야만 하는 번거로움이 있다. 여기서 System.Windows.Forms가 Namespace다(Type 및 Member는 사이에 .을 넣지 않으므로 구분이 쉽게 될것이다). 이 Namespace를 생략하고 쓸수 있는 방법이 있는데 이것이 바로 using이다.

즉 using System.Windows.Forms를 선언하여 컴파일러에게 namespace 사용을 알려 준 후 MessageBox.Show("Hellow World")라고 호출하면 같은 기능을 수행하게 된다.

 

4. delete가 존재하지 않는다.

   C#은 new로 메모리를 할당하는 것은 C++과 같으나 메모리를 삭제하는 delete가 존재하지 않는다. 메모리 삭제는 가비지컬렉터가 사용하지 않는 시점에 알아서 삭제를 해 준다.

 

5. 포인터가 없어졌다.

   C, C++에서 초보자를 괴롭히는 것이 포인터이다. 포인터 교육시 잘사용하는 예제는 다음과 같다.

void Swap(int *data1, int *data2)

{

     int dataBuff;

     dataBuff = *data1;

     *data1 = *data2;

     *data2 = dataBuff;

}

int nValue1 = 100, nValue2 = 200;

Swap(&nValue1, &nValue2);

   뭐 다들 알겠지만 Swap에 nValue1과 nValue2의 주소를 넘겨 주어 주소의 내용을 서로 바꾸므로 실제 내용이 nValue1은 200으로 nValue2는 100으로 바뀌어 들어가게 된다.

   C++에서는 다음과 같이 레퍼런스 개념이 생겼다.

void Swap(int &data1, int &data2)

{

     int dataBuff;

     dataBuff = data1;

     data1 = data2;

     data2 = dataBuff;

}

int nValue1 = 100, nValue2 = 200;

Swap(nValue1, nValue2);

   레퍼런스를 사용함으로 해서 포인터를 사용한것과 같이 Swap 기능을 구현한 것이다. 좀 보기가 편해진 감이 있다.

   C#에서는 레퍼런스만 사용할 수 있는데 사용 또한 다음과 같이 바뀌었다.

void Swap(ref int data1, ref int data2)

{

     int dataBuff;

     dataBuff = data1;

     data1 = data2;

     data2 = dataBuff;

}

int nValue1 = 100, nValue2 = 200;

Swap(ref nValue1, ref nValue2);

   ref 대신 in(입력 전용), out(출력 전용)을 사용할 수 있다.

 

6. 기본적으로 sizeof를 사용할 수 없다.

  C나 C++에서 sizeof는 많이 사용하는 기능이다. 그러나 C#에서는 sizeof가 내부적으로 메모리를 직접 다루는 명령어 이므로 권장하지 않는다. sizeof는 구조체 복사와 파일에서부터 읽을 때 그 구조체의 크기를 구할 때 가장 많이 사용한다. 예를 들어 다음과 같은 경우이다.

typedef struct Size

{

     int cx;

     int cy;

}

Size size1(10, 20), size2;

memcpy(&size2, &size1, sizeof(Size));

 이것은 C#에서 단순히 =을 사용하면 복사가 이루어 진다.

struct Size

{

     public int cx;

     public int cy;

}

Size size1(10, 20), size2;

size2 = size1;

  또한 파일로부터 읽고 쓸때는 구조체 Member Method로 Save와 Load를 만들어 개별 Member 변수를 읽을 수 있도록 구성하면 된다.

  참고로 꼭 sizeof를 사용해야 하는 경우라면 sizeof를 사용하는 코드를 unsafe{}로 감싸 주고, 프로젝트 속성에서 안전하지 않은 코드 블록 허용을 True로 설정해야 한다. 그러나 호환성도 떨어지고 안전하지 않으므로 가능하면 사용하지 말기 바란다.

 

7. 데이터 형

   데이터 형은 C#과 C++은 거의 같다. 다른 부분이라면 char, long, decimal이다. char는 하나의 문자를 저장하는 기능을 수행하며 C++과 다르게 2byte를 차지 한다. C++에서는 ASCII 코드를 사용하였으나 C#에서는 유니코드(전세계언어를 2byte코드로 나타낸것)를 사용한다. 참고로 1byte를 차지하는 데이터 형은 byte와 sbyte가 있다. long은 C++에서는 4byte를 차지 했으나 C#에서는 8byte를 차지한다. decimal은 8byte 상수로 추가되었다.

 

8. 배열 선언

   C++에서는 배열을 다음과 같이 설정했을 것이다.

   int arr[30];

   C#에서는 다음과 같이 선언한다.

   int[] arr = new int[30];

 

9. if 조건문

  int a = 1, b = 8;

   if(a && b >= 5)

  위 문장은 C++에서 당연히 참이다. 그러나 C#에서는 컴파일 에러가 나타난다. 위 문장은 if(a!=0 && b >= 5)로 수정해야만 한다. 조건문 내부에는 boolen으로 구성되어야 한다. 이것은 C++에서도 마찬가지였다. 그러나 C#에서는 형변환 규칙이 엄격해졌다. 따라서 위 문장에서 a는 boolen변수가 아니므로 에러가 나타나는 것이다. 이것은 다음과 같은 오류를 줄여 준다.

if(a == 1)이라고 해야 하는 자리에 if(a = 1)라고 하면 위와 같은 이유로 C#에서는 컴파일 에러를 내어 준다. 이 실수는 한번쯤은 해봤으리라 예상이 된다.

그러나 C#에서도 a가 boolen으로 선언되었다면 if(a = 1)은 에러가 나타나지 않을 것이다.

 

10. switch 문

switch(a)
{
   case 3:
       b = 7;
   case 4:
       c = 3;
       break;
}


  위문장은 C++에서는 이상이 없으나 C#에서는 컴파일 에러가 나타난다. break없이 다음 case로 넘어가는 것을 허용하지 않는다. 예외로 아래와 같이 첫 번째 case 문에 아무것도 하지 않고 다음 case로 넘어 가는 것은 허용한다.

switch(a)
{
   case 3:
   case 4:
       c = 3;
       break;
}

 

11. 반복문

int[] arr = new int[30];
for(int i = 0; i < arr.Length; i++)
{
   Console.Write("{0}", arr[i]);
}

  위 문장을 실행하면 0 이 30번 출력된다(new를 사용하면 데이터가 0으로 초기화 되는 것을 보장한다). C#에서는 다음과 같이 해도 같은 기능을 수행한다.

int[] arr = new int[30];
foreach(int value in arr)
{
   Console.Write("{0}", value);
}

  참고로 Write의 {0}는 첫 번째 인자라는 뜻이다.

 

12. static 메서드

   C++에서는 외부변수와 외부함수 선언(C기능)이 가능했다. 그러나 C#은 완벽한 OOP개념의 언어이므로 이 두가지를 전혀 지원하지 않고 Type 내에 선언해야 한다. Type내에 메서드를 선언하면 호출시 다음과 같이 해야만한다.

class Calc
{
     public double Add(double value1, double value2)
     {
         return value1 + value2;
     }
}

   Calc calc = new Calc;

   double result = calc.Add(1, 2);

   그러나 Add 메서드를 호출하기 위하여 무조건 위와 같이 해야 하는 것은 약간 번거롭다. 따라서 Type내의 메서드를 static으로 선언하는 것을 지원한다.

class Calc
{
     public static double Add(double value1, double value2)
     {
         return value1 + value2;
     }
}

   double result = Calc.Add(1, 2);

   즉 static 메서드는 Class이름.메서드의 형태로 바로 호출할 수 있게 해준다. 참고로 9번 반복문에서 Console.Write는 Write를 static 메서드로 선언 했기 때문에 호출가능한 구조이다.

 

13. C++ 은 다중 상속이 가능하나 C#은 단일 상속만 가능하다.

  Class Calc1, Calc2, Calc3가 있다고 가정하고 Calc3가 Calc1의 기능과 Calc2의 기능을 모두 사용해야 한다면, C++에서는 class Calc3 : public Calc1, public Calc2 라고 선언하여 가능했다. 그러나 C#에서는 이것을 허용하지 않는다. 굳이 사용하고자 한다면 Calc2를 Calc1으로부터 상속받도록 하고 Calc3는 Calc2로 상속받아 계층적 구조를 이루어야만 한다.

  이것은 어떤면에서 C#의 단점이라고 할 수 있다. 그러나 다중상속은 잘못 사용하면 프로그래머에게 엄청난 오류를 범하게 한다고 한다. 그 오류의 가능성을 사전에 차단했다라고 보면 될듯하다.

 

  기본 문법 설명은 여기까지 하겠다. 나머지는 프로그래밍을 하면서 차츰익히기 바란다.

  여기서 이해가 안된다고 너무 괴로워하지 말기 바란다. 프로그래밍은 모든 문법을 다 외워서 하는 것이 아니다. 사용하면서 저절로 익히는 것이다.


'Computerscience > C#' 카테고리의 다른 글

c# 훅크 사용법[스크랩]  (0) 2009.08.13
DatagrideView에 쿼리 반환값 넣기[기초]  (0) 2009.02.13
DB 연동하기  (0) 2009.02.13
메세지박스 활용법  (0) 2008.09.04
C# 스토워드 프로시져로 쿼리 날리기.  (0) 2008.09.03