'생성자'에 해당되는 글 2건

Programming/.NET

클래스의 생성자는 클래스명과 같은 메서드를 정의함으로서 구현할 수 있습니다.

 

class MyClass
{
    public MyClass()
    {

    }
}

 

생성자는 말 그대로 클래스의 개체가 생성될때 호출되는 메서드입니다. 여기에 각종 변수의 초기화나 혹은 필요한 매개변수를 받아 클래스에서 사용되는 데이터를 초기화 하는 것이 가능합니다.

 

class MyClass
{
    public MyClass(int i, int j)
    {
        MyValue = i + j;
    }

    public int MyValue
    {
        get;
        set;
    }
}

 

예제에서 클래스는 개체생성시 두개의 매개변수를 받아 MyValue라는 속성값을 초기화 하도록 하였습니다.

 

static void Main(string[] args)
{
    MyClass m = new MyClass(10, 20);
    Console.WriteLine(m.MyValue);
}

 

소멸자는 GC에 의해 해당 개체의 자원을 해제할때 호출되는 메서드입니다. 이 메서드는 클래스이름앞에 ~문자만 붙이면 소멸자 메서드가 됩니다.

 

class MyClass
{
    public MyClass(int i, int j)
    {
        MyValue = i + j;
    }

    public int MyValue
    {
        get;
        set;
    }

    ~MyClass()
    {

    }
}

 

소멸자는 임의로 호출하는 것이 불가능하며 GC가 수행될때 호출됩니다. 소멸자는 그 특성으로 인해 소멸자에서 뭔가를 임의로 처리하는 경우는 거의 없습니다. 간혹 비관리메모리를 사용한 경우 GC에 의해 해제될 수 없기에 소멸자에서 명시적으로 해제에 필요한 코드를 담는 경우가 있기는 하지만 활용도가 크지는 않습니다.

 

class MyClass : IDisposable
{
    IntPtr myMemory;

    public MyClass()
    {
        myMemory = Marshal.AllocCoTaskMem(1024);
    }

    public void Dispose()
    {
        Marshal.FreeCoTaskMem(myMemory);
    }

    ~MyClass()
    {
        Dispose();
    }
}

 

소멸자가 있는 클래스에 new로 개체를 생성하면 이 개체를 힙에 저장하고 동시에 '종료큐'라고 하는 곳에도 개체를 등록하게 됩니다. GC가 이 개체를 힙에서 제거하고자 할때 종료큐에 들어간 개체를 Freachable에 옮기게 되면 CLR에 의해 생성된 스레드가 Freachable안에 존재하는 개체의 소멸자를 호출한뒤 Freachable안에서 개체를 제거하게 됩니다. 그리고 힙에 존재하는 개체는 GC가 실행될때 비로소 힙에서 제거됩니다. 이 복잡한 과정때문에 소멸자가 존재하는 클래스는 GC에 부담스럽게 작용하고 때문에 꼭 필요하지 않다면 소멸자를 별도로 생성하는건 권장하지 않습니다.

 

하지만 만약 클래스의 Dispose() 메서드가 명시적으로 호출될 수 있는 상황이고 이때 GC가 소멸자를 다룰 필요가 없는 경우라면 Dispose() 메서드에서 GC의 SuppressFinalize() 메서드를 호출하여 종료큐에서 개체를 제거하도록 할 수 있습니다. 이렇게 되면 GC가 소멸자를 고려할 필요가 없으므로 GC의 부담을 줄여줄 수 있게 됩니다.

 

class MyClass : IDisposable
{
    IntPtr myMemory;

    public MyClass()
    {
        myMemory = Marshal.AllocCoTaskMem(1024);
    }

    public void Dispose()
    {
        objectRemove(true);
    }

    private void objectRemove(bool self_call)
    {
        Marshal.FreeCoTaskMem(myMemory);

        if (self_call)
            GC.SuppressFinalize(this);
    }

    ~MyClass()
    {
        objectRemove(false);
    }
}

'Programming > .NET' 카테고리의 다른 글

[C#] fixed  (0) 2018.06.13
[C#] DateTime  (0) 2018.05.29
[C#] 생성자와 소멸자  (0) 2018.05.23
[C#] 개체의 생성과 해제  (0) 2018.05.15
[C#] 호출자 정보 (CallerMemberName / CallerFilePath / CallerLineNumber)  (0) 2018.05.08
[C#] 람다식 (Lambda expression)  (0) 2018.05.02
0 0
Programming/C C++
Class사용시에는 Class의 Object를 생성한 후 각 Member함수를 호출하여 Member변수의 값을 설정합니다.

이와는 달리 Class의 생성자는 Object생성과 동시에 원하는 Member변수를 초기화 할 수 있습니다.

#include <iostream.h>
#include <string.h>

class exam{
  private:
    char name[15];
    int kuk;
    int mat;
    int eng;
 
  public:
    exam(char *nm, int k, int m, int e);
   
    void name_input(char *nm);
    void memberprint();
   
    int kuk_input(int pt);
    int mat_input(int pt);
    int eng_input(int pt);
};

exam::exam(char *nm, int k, int m, int e)
{
  strcpy(name, nm);
 
  kuk = k;
  mat = m;
  eng = e;
}

void exam::name_input(char *nm)
{
  strcpy(name, nm);
}

int exam::kuk_input(int pt)
{
  int ptp = pt;
 
  if (pt >= 90)
    ptp = pt + 3;
 
  kuk = pt;
 
  return ptp;
}

int exam::mat_input(int pt)
{
  int ptp = pt;
 
  if (pt >= 90)
    ptp = pt + 3;
 
  mat = pt;
 
  return ptp;
}

int exam::eng_input(int pt)
{
  int ptp = pt;
 
  if (pt >= 90)
    ptp = pt + 3;
 
  eng = pt;
 
  return ptp;
}

void exam::memberprint()
{
  cout << "학생이름 : " << name << endl << endl;
  cout << "국어점수 : " << kuk << endl;
  cout << "수학점수 : " << mat << endl;
  cout << "영어점수 : " << eng << endl;
}

main()
{
  exam student("young soo", 90, 100, 80);
 
  student.memberprint();
  return 0;
}


Class안에 exam(char *nm, int k, int m, int e); 으로 생성자를 선언하고 main안에서 exam student("young soo", 90, 100, 80); 구문을 통해 생성자로 초기값을 설정합니다.

생성자의 선언은 Class이름과 동일하게 하고 인수를 설정하여 어떠한 Member에 값을 설정할지를 지정하면 됩니다. 생성자의 본체도 Class이름으로 다음과 같이 작성되어 해당 Member에 대해 초기화를 수행하도록 합니다.
exam::exam(char *nm, int k, int m, int e)
{
  strcpy(name, nm);
 
  kuk = k;
  mat = m;
  eng = e;
}

생성자는 초기화 전용입니다. 따라서 return을 통해 값을 반환할 수 없습니다. 반환값없는 전용이므로 이 생성자함수에 void나 int처럼 return형식을 지정하는 것 자체가 무의미한 것입니다.

생성자를 통해 값을 초기화 하려면 Class의 Object생성시 바로 인수를 건네주도록 합니다. 그러면 자동으로 생성자가 호출되어 해당 Class에 대한 초기화처리를 하게 됩니다.

exam student("young soo", 90, 100, 80);

소멸자는 Class이름앞에 ~문자를 붙여 선언하는 것으로 이 소멸자는 Class의 Member함수를 호출하고 그 함수를 빠져나올때 자동으로 호출되는 특징을 가지고 있습니다.

#include <iostream.h>
#include <string.h>
class exam{
  private:
    char name[15];
 
  public:
    exam(char *nm);
    ~exam();
   
    void name_input(char *nm);
    void memberprint();
};

exam::exam(char *nm)
{
  strcpy(name, nm);
}

exam::~exam()
{
  cout << "소멸자가 호출됨" << endl;
}

void exam::name_input(char *nm)
{
  strcpy(name, nm);
}

void exam::memberprint()
{
  cout << "학생이름 : " << name << endl << endl;
}

main()
{
  exam student("young soo");
 
  student.memberprint();
  return 0;
}


Class안에 ~exam();으로 소멸자를 선언하였습니다. 이 소멸자는 Class내의 함수가 호출되고 난 후마다 자동 호출됩니다.


소멸자는 어떤값도 반환하지 않고 또 어떠한 인수도 전달하지 않습니다. 또한 소멸자를 정의하는 함수부분에는 개발자가 Class의 함수호출이 이루어지고 난 다음에 필요한 부분을 작성하기만 하면 되는 것입니다.

1. 생성자 Overloaded

C++에서의 함수는 Overloaded가 가능합니다. 즉, 같은 이름의 함수에 다른 인수의 특성에 따라 다른처리를 행하는 것이 가능한 것입니다.

이러한 Overloaded는 일반 함수뿐만 아니라 생성자에도 적용할 수 있습니다. 물론 생성자에 Overloaded를 선언하는 방법도 일반함수와 다를게 없습니다.

#include <iostream.h>
#include <string.h>

class exam{
  private:
    char name[15];
    int kuk;
    int mat;
    int eng;
 
  public:
    exam();
    exam(char *nm, int k, int m);
    exam(char *nm, int k, int m, int e);
   
    void memberprint();
};

exam::exam()
{
  strcpy(name, "noname");
 
  kuk = 0;
  mat = 0;
  eng = 0;
}

exam::exam(char *nm, int k, int m)
{
  strcpy(name, nm);
 
  kuk = k;
  mat = m;
  eng = 200;
}

exam::exam(char *nm, int k, int m, int e)
{
  strcpy(name, nm);
 
  kuk = k;
  mat = m;
  eng = e;
}

void exam::memberprint()
{
  cout << "학생이름 : " << name << endl;
  cout << "국어점수 : " << kuk << endl;
  cout << "수학점수 : " << mat << endl;
  cout << "영어점수 : " << eng << endl << endl;
}

main()
{
  exam student_fir;
  student_fir.memberprint();
 
  exam student_sec("young soo", 90, 100);
  student_sec.memberprint();
 
  exam student_thr("soo young", 90, 100, 50);
  student_thr.memberprint();
  return 0;
}


Class에서 exam세개를 선언하였으며 각각의 함수마다 인수를 틀리게 하여 Overloaded화 하였습니다. Class에서 생성자를 Overloaded로 선언하면 각 함수에 맞는 정의도 다음과 같이 해주어야 합니다.

exam::exam()
{
  strcpy(name, "noname");
 
  kuk = 0;
  mat = 0;
  eng = 0;
}

exam::exam(char *nm, int k, int m)
{
  strcpy(name, nm);
 
  kuk = k;
  mat = m;
  eng = 200;
}

exam::exam(char *nm, int k, int m, int e)
{
  strcpy(name, nm);
 
  kuk = k;
  mat = m;
  eng = e;
}


이렇게 하면 생성자를 호출할때마다 해당 인수에 따라서 다른 형태로 초기화를 수행할 것입니다.

주의할 것은 Class의 Object를 생성할때 다른 Overloaded 생성자를 호출하고자 한다면 다음과 같이 다른 이름의 Object를 사용해야 한다는 것입니다.

exam student_fir;
student_fir.memberprint();
 
exam student_sec("young soo", 90, 100);
student_sec.memberprint();
 
exam student_thr("soo young", 90, 100, 50);
student_thr.memberprint();


만일 Class의 Object가 배열로 생성되면 []를 이용해 몇번째 배열의 Object에서 Member를 호출할지를 지정해야 하는데 이때 위와 같은 생성자의 특징을 이용하면 {}를 사용해 배열의 Member를 한꺼번에 초기화 할 수도 있습니다.

#include <iostream.h>
#include <string.h>

class exam{
  private:
    char name[15];
    int kuk;
    int mat;
    int eng;
 
  public:
    exam(char *nm, int k, int m, int e);
   
    void memberprint();
};

exam::exam(char *nm, int k, int m, int e)
{
  strcpy(name, nm);
 
  kuk = k;
  mat = m;
  eng = e;
}

void exam::memberprint()
{
  cout << "학생이름 : " << name << endl;
  cout << "국어점수 : " << kuk << endl;
  cout << "수학점수 : " << mat << endl;
  cout << "영어점수 : " << eng << endl << endl;
}

main()
{
  exam student[2] = {
    exam("soo young", 90, 100, 50),
    exam("young soo", 59, 65, 88)
  };
 
  student[0].memberprint();
  student[1].memberprint();
  return 0;
}


exam Class의 student Object를 2로 하여 2개의 배열로 Object가 생성되도록 하였습니다.

이후 초기화는 {와 }사이에 묶어 exam("soo young", 90, 100, 50)과 exam("young soo", 59, 65, 88)으로 각각의 배열에 이름과 점수를 초기화 합니다.

'Programming > C C++' 카테고리의 다른 글

[Visual C++] 관련 라이브러리  (0) 2012.06.21
표준 Library 함수 - Memory 관련 함수  (0) 2011.06.16
[C, C++] Class구현시 생성자와 소멸자 활용  (0) 2011.06.01
[C, C++] Class  (0) 2011.05.25
[C, C++] cout 서식지정  (0) 2011.04.14
[C, C++] 구조체  (1) 2011.04.13
0 0
1
블로그 이미지

클리엘