C++ 중급 - Constructor

타입·2024년 1월 12일
0

C++ 공부

목록 보기
4/17
  • 생성자/소멸자 호출의 정확한 원리
    컴파일러가 기반 클래스 및 멤버 데이터의 생성자/소멸자를 호출하는 코드를 생성
struct BM {};
struct DM {};
struct Base
{
	BM bm;
	Base()		: bm() {}
	Base(int a)	: bm() {}
	~Base()     { bm.~BM(); }
};
struct Derived : public Base
{
	DM dm;
	Derived()      : Base(), dm() {}
	Derived(int a) : Base(), dm() {}
	~Derived()     { dm.~DM(); ~Base(); }
};
  • 생성자 호출 순서
    1 기반 클래스 멤버의 생성자
    2 기반 클래스의 생성자
    3 파생 클래스 멤버의 생성자
    4 파생 클래스의 생성자
    (소멸자는 역순)

  • 사용자가 생성자 호출 순서를 변경 불가
    코드를 수정하여도 항상 기반 클래스 생성자가 먼저 호출되고 멤버 데이터의 생성자가 호출

  • 컴파일러가 생성한 코드는 항상 디폴트 생성자를 호출
    디폴트 생성자가 없는 경우 반드시 다른 생성자를 호출하는 코드를 작성해야함


  • Base From Member
class Buffer
{
public:
	Buffer(std::size_t sz) { std::cout << "initialize buffer" << std::endl;}
	void use() 			   { std::cout << "use buffer" << std::endl;}
};

class Stream
{
public:
	Stream(Buffer& buf) { buf.use();}
};

int main()
{
	Buffer buf(1024);
	Stream s(buf);
}

문제 없는 코드

...

class StreamWithBuffer : public Stream
{
	Buffer buf{1024};
public:
	StreamWithBuffer() : Stream(buf) {}
};

int main()
{
	StreamWithBuffer swb;
}

기반 클래스에서 버퍼를 추가하면 멤버 데이터의 생성자보다 기반 클래스의 생성자가 먼저 불려
먼저 사용하고 이후 초기화해버리는 문제 발생

...
class StreamBuffer
{
protected:
	Buffer buf{1024};
};

class StreamWithBuffer : public StreamBuffer,
	 			         public Stream
{
public:
	StreamWithBuffer() : Stream(buf) {}
};

생성자 호출 문제를 해결하기 위하여 다중 상속 사용 - Base From Member (C++ IDioms)
별도 기반 클래스를 추가하고 먼저 상속받은 StreamBuffer의 생성자가 먼저 불림

  • 생성자에서는 가상함수가 동작하지 않음
    기반 클래스의 생성자에서 가상함수가 동작한다면 초기화되지 않은 파생 클래스의 멤버를 사용해버리는 문제가 있을 수 있음
class Base
{
public:
	Base()     { vfunc(); } // Base vfunc
	void foo() { vfunc(); } // Derived vfunc
	virtual void vfunc() { std::cout << "Base vfunc" << std::endl; }
};

class Derived : public Base
{
	int data{10};
public:
	virtual void vfunc() override
	{ 
		std::cout << "Derived vfunc : " << data << std::endl; 
	}
};

int main()
{
	Derived d;
}
profile
주니어 언리얼 프로그래머

0개의 댓글