[Step.02-2] 클래스(class), 핸들(^), 그리고 구조체(struct)
gcnew로 생성하지 않기
C++/CLI는 클래스를 생성할 때 ‘gcnew’를 사용하지 않고 생성할 수도 있습니다.
< 리스트 1. ‘gcnew’를 사용하지 않고 클래스 생성하기 >
#include "stdafx.h"
#include <stdio.h>
using namespace System;
ref class ManagedTest
{
public:
ManagedTest() { Console::WriteLine(L"New ManagedTest"); }
~ManagedTest() { Console::WriteLine(L"delete ManagedTest"); }
void func() { Console::WriteLine(L"Call func() - {0}", nNumber ); }
int nNumber;
};
void foo1()
{
ManagedTest MTest;
MTest.nNumber = 1;
MTest.func();
}
void foo2()
{
ManagedTest^ MTest = gcnew ManagedTest();
MTest->nNumber = 2;
MTest->func();
}
int main(array<System::String ^> ^args)
{
foo1();
foo2();
getchar();
return 0;
}
< 결과 >
<리스트 1>의 ManagedTest MTest; 는 비 관리 C++처럼 GC가 아닌 스택 영역에 생성하는 것으로 착각할 수도 있겠지만 전혀 아닙니다. 클래스를 생성하면 언제나 GC 영역에 만들어집니다.
위의 코드는 그냥 ‘gcnew’ 사용을 우리가 생략하고 컴파일러가 대신 써 준다고 생각하시면 됩니다.
void foo1()
{
ManagedTest MTest;
MTest.nNumber = 1;
MTest.func();
}
은 컴파일러에 의해서 아래의 코드로 바뀝니다.
void foo1()
{
ManagedTest^ MTest = gcnew ManagedTest();
MTest->nNumber = 1;
MTest->func();
delete MTest;
}
위의 코드를 보시면 아시듯이 gcnew를 사용하지 않고 클래스를 생성하면 우리가 직접 delete를 쓰지 않아도 되는 편리함을 얻을 수 있습니다.
gcnew를 사용하지 않는 것은 C#에서 ‘using’을 간략화 시킨 것으로 생각하면 좋습니다.
< C#의 using 문 사용 예 >
using (Graphics g = this.CreateGraphics())
{
g.DrawLine(Pens.Black, new Point(0,0), new Point(3,5));
}
value 클래스
관리 클래스는 복사 생성자와 대입 연사자를 가지지 못하므로 아래의 코드는 컴파일 에러가 발생합니다.
< 리스트 2. >
#include "stdafx.h"
#include <stdio.h>
using namespace System;
ref class C {
int i;
};
void func(C c) {}
int main()
{
C c;
C d;
func(c); // 에러
d = c; // 에러
}
그러나 클래스를 ‘ref’가 아닌 ‘value’ 클래스로 정의하면 위의 코드는 컴파일 할 수 있습니다.
#include "stdafx.h"
#include <stdio.h>
using namespace System;
value class C {
int i;
};
void func(C c) {}
int main()
{
C c;
C d;
func(c); // 에러
d = c; // 에러
}
value 클래스는 클래스간 복사를 할 수 있는 능력이 있습니다. 이 복사는 비트 단위의 복사로 이른바 ‘memcpy’와 같은 복사입니다.
value 클래스는 복사를 할 수 있으므로 value 클래스의 멤버는 절대 복사 가능한 멤버만 가질 수 있습니다. 그래서 아래와 같은 value 클래스 C는 컴파일 에러가 발생합니다.
ref class A
{
int i;
};
value class C
{
A a;
};
또 value 클래스의 특징으로는 ref 클래스가 GC에서 만들어지는 것과 달리 스택에 만들 수 있습니다.
value class C
{
};
C c;
위 코드에서 C 클래스는 스택에 만들어집니다(물론 gcnew를 사용하면 GC에 만들어집니다)
value 클래스의 특징은 좀 더 있는데 위에 설명한 것들과 포함해서 아래와 같이 정리할 수 있습니다.
value 클래스의 특징
1. 기본 생성자를 가질 수 없다.
2. 복사 생성자를 가질 수 없다.
3. 대입 연산자를 가질 수 없다.
4. 소멸자를 가질 수 없다.
5. finalize를 가질 수 없다.
6. 클래스간 복사를 할 수 있다.
7. 복사 불가능한 것을 멤버로 가질 수 없다(ref 클래스 등).
8. 스택에 생성할 수 있다.
9. 다른 클래스를 계승할 수 없다(단 interface는 가능하다)
관리 클래스를 파라메터로 넘기기
ref class A
{
int i;
};
void foo1( A a )
{
}
함수 foo1의 파라미터 정의는 클래스 A가 value 클래스일 때만 사용할 수 있습니다. 그러므로 아래와 같이 foo1의 파라미터를 정의해야 합니다.
void foo1( A^ a )
{
}
그 외….
C++/CLI에서 참조는 ‘%’을 사용합니다. 이것은 비 관리의 ‘&’와 구별이 됩니다.
%는 아래와 같은 경우에 유용하게 사용할 수 있습니다.
void foo( A^ a )
{
}
A a;
// foo( a ); // 에러
foo( %a ); // 성공
{
i=5;
}
// 참조형을 참조로 넘기기
void refbyref(String^%s)
{
s="newstring";
}
void main()
{
int i=1;
valuebyref(i);
String^s="basestring";
refbyref(s);
}
구조체는 관리나 비 관리나 다른 점은 없습니다.
참조와 구조체는 너무 짧게 끝나버렸네요^^;
'Programming > C++/CLI' 카테고리의 다른 글
C++/CLI Singleton (0) | 2010.10.22 |
---|---|
C++/CLI 데이터 타입에 따른 리턴값, 파라미터 처리 (ActvieX ↔ C++/CLI ↔ C#) (0) | 2010.10.05 |
[Step 02-1] 클래스(class), 핸들(^), 그리고 구조체(struct) (0) | 2010.10.05 |
C + + 프로그래머를위한 C + + / CLI 소개 (0) | 2010.10.05 |
C++/CLI article in MSDN (0) | 2010.10.02 |