Item 5: 컴파일러가 자동으로 만들어 주는 멤버함수

  • 기본생성자(default constructor)
  • 복사생성자(copy constructor)
  • 복사 대입 연산자(copy assignment operator)
  • 소멸자(destructor)

이때 만들어지는 함수는 모두 기본형(default)이다. 그리고 모두 public이며 inline함수이다.(항목 30)

class Empty{};

위와 같이 만들어 두면 컴파일러가 자동으로 만들어 주는 함수가 있는데 아래와 같다고 보면 된다.

class Empty {
public:
    Empty() { ... }           // 기본생성자
    Empty(Empty& rhs) { ... } // 복사생성자
    ~Empty() { ... }          // 소멸자

    Empty& operator=(const Empty& rhs) { ... } // 복사 대입 연산자
};

컴파일러가 자동으로 이들을 만들어 주는 경우.

Empty e1;             // 기본생성자, 소멸자

Empty e2(e1);         // 복사생성자

e2 = e1;              // 복사 대입 연산자

컴파일러가 만드는 함수가 하는 일

생성자 / 소멸자

  • 기본클래스 및 비정적 데이터 멤버의 생성자/소멸자 호출

이때 소멸자는 기본클래스의 소멸자가 비가상소멸자이면 마찬가지로 비가상 소멸자로 만들어진다.

복사생성자/복사대입연산자

  • 원본 객체의 비정적 데이터를 사본 객체쪽으로 단순 복사

간단한 예를 살펴보자.

template<typename T>
class namedObject {
public:
    NamedObject(const char*name, const T& value);
    NamedObject(const std::string& name, const T& value);
    ...

private:
    std::string nameValue;
    T objectValue;
};

여기에서는 컴파일러가 기본생성자를 만들지 않는다(사용자 이미 다른 생성자를 만들었음으로) . 대신 컴파일러가 필요하다고 판단할 경우, 복사생성자와 복사대입연산자를 만들 수 있다.

NamedObject<int> no1("Smallest Prime Number", 2);
NamedObject<int> no2(no1);         // 여기서 복사 생성자를 호출함.
  • nameValue의 경우 string 타입으로, 이 클래스는 이미 복사생성자를 가지고 있어 이 함수에 위임하면됨.
  • objectValue의 경우 int 타입으로 단순 비트 카피하면 됨.

복사대입연산자의 경우 원리는 위와 비슷하다, 하지만 컴파일러는 최종 결과 코드가 적법하고(legal) 이치에 맞아야(resonable)만 자동으로 생성해준다. 그렇지 않으면 컴파일 에러를 준다.

아래의 예를 보자.

template<typename T>
class namedObject {
public:

    NamedObject(std::string& name, const T& value);
    ...                          // operator= 함수는 선언되지 않음.

private:
    std::string& nameValue;   // 참조자 타입으로 변경
    const T objectValue;      // 상수 타입으로 변경
};

위 코드를 아래와 같이 사용한다고 하자.

std::string newDog("Persephone);
std::string oldDog("Satch");

Nameobject<int> p(newDog, 2);
NameObject<int> s(oldDog, 36);

p = s;                    // p는 어떻게 되어야 하나?

p.nameValue 참조자인데 어떻게 해야 하나?

1) 참조자 자체가 바뀌어야 하나?

-> 하지만 C++ 참조자는 한번 할당 되면 변경할 수 없다.

2) p.nameValue가 참조하는 string이 변경되어야 하나?

-> 실제 대입연산에 직접관여하지 않는 객체까지 영향을 받음. 맞는 경우인가?

이런한 경우 컴파일 에러가 발생한다.

참조자나, 상수 객체를 데이터 멤버로 갖고 있는 클래스에 대입 연산을 지원하려면 컴파일러가 아닌 사용자가 직접 알아서 만들어 줘야 한다.

베이스 클래스에서 private으로 선언된 복사대입연산자를 갖는 경우, 파생 클래스는 암시적 복사대입연산자를 갖을 수 없다. 콜이 안돼.

results matching ""

    No results matching ""