1. 멤버 객체 선언 시, 원하는 생성자를 호출하는 방법은?
Initialize() 함수나 생성자의 블록 내에서 대입 생성 시 생성자가 두 번 호출되어 비효율적이지만,
아래와 같이 생성자의 멤버 이니셜라이저를 사용하거나, 멤버 변수 선언 옆에 대입 생성자를 호출하면 생성자가 한 번만 호출된다.
class A
{
public:
A(){}
A(int _i){}
}
class B
{
public:
B() : a(10){} // 이니셜라이저 사용
public:
A a = A(10); // 혹은 대입 생성
}
2. 부모에서 멤버로 선언한 객체의 생성을 원하는 생성자로 하는 방법은?
생성자 혹은 다른 함수에서 m_A = A(10); 와 같이 따로 생성해줄 수 있다. 그러나 이 방법은 이미 생성된 m_A에 또 다시 A(10)으로 생성해서 복사 대입하므로 비효율적이다.
결국 멤버 객체의 생성자들 중 원하는 생성자에 맞는 매개변수를 가진 다른 생성자를 하나 더 만들어주는 게 낫다.
class A
{
public:
A(){}
A(int _i){}
}
class Parent
{
public:
Parent(int _i) : m_A(_i) { }
A m_A;
}
class Child : public Parent
{
public:
Child(){m_A = A(10);} //이렇게 생성자 블록 내에서 따로 대입하거나
Child(int _i) : Parent(i) {} // 생성자를 따로 만들어주거나
}
3. 함수의 반환 타입은 참조(&)형인가?
아니다. 함수 반환 시 별도의 객체가 생성되며 이후 자동 소멸된다.
다만 함수의 반환타입을 &형으로 선언하면 참조형이 반환된다. 즉, 객체가 따로 생성되지 않는다. 참조형 변수에 이를 대입할 수 있는데, 같은 메모리를 공유한다.
class A
{
}
A& func(A& a)
{
return a;
}
int main()
{
A a;
A& aRef = func(a);
//a 와 aRef는 같은 메모리를 사용함.
}
4. 부모와 자식의 this의 값은 같은가?
같다. 둘 다 객체의 첫번째 메모리를 가리킨다.
5. 첫 번째 메모리는 부모와 자식의 멤버 변수 중 누가 차지하는가?
부모의 것이 먼저 온다.( 더 낮은 주소값을 갖는다)
그리고 부모의 첫 번째 멤버의 주소는 객체의 첫 번째 주소(this)와 같다.
class C
{
public:
C() { cout << "C 기본생성 : " << this << endl; }
C(int _i) { cout << "C 매개변수 생성" << endl; }
~C() { cout << "C 기본 소멸" << endl; }
private:
};
class B
{
public:
B(){ cout << "B 기본생성 : "<< this << endl; }
~B() { cout << "B 기본 소멸" << endl; }
public:
int m_iB = 10;
C m_C;
};
class A : public B
{
public:
A() :m_iA(1) { cout << "A 기본생성 : " << this << endl;}
A(const A& rhs): m_iA(rhs.m_iA) { cout << "A 복사생성 : " << this << endl;}
~A() { cout << "A 기본 소멸" << endl; }
void Inc() { m_iA++; }
int GetA() { return m_iA; }
public:
int m_iA = 20;
};
int main()
{
A* a = new A();
cout << "a 생성 완료" << endl;
cout << a << endl; //00B807A0
cout << &a->m_iA << endl;//00B807A8
cout << &a->m_iB << endl; //00B807A0
cout << &(a->m_C) << endl; //00B807A4
system("pause");
}
6. 소멸자에 virtual 키워드를 붙이는 이유는?
부모 포인터형 변수를 delete했을 때, 자식의 소멸자를 호출하기 위함.
소멸자도 가상 함수처럼 동작하기 때문에 virtual을 붙여주어야 실제 객체 타입에 해당하는 소멸자가 호출된다.
만약 virtual을 붙이지 않으면 부모의 소멸자만 호출되고, 이 때 만약 자식 클래스의 멤버로 동적 할당된 메모리를 가리키는 유일한 포인터가 있고, 자식 클래스의 소멸자에서 그 메모리를 해제하도록 해놓았다면, 메모리 누수로 이어짐.
7. 부모 객체에 자식 객체 대입이 가능한가? 포인터는 가능한데...
가능하다. 다만 객체간의 캐스팅은 불가능하다.