본문 바로가기
c++

[C++]멤버 이니셜라이저(Member Initializer)를 이용한 멤버 초기화

by goblin- 2023. 2. 27.

클래스 안에 여러 개의 객체를 멤버로 지니고 있는 클래스의 같은 경우 객체가 생성되면 객체 안에 있는 여러 개의 객체가 함께 생성된다.(여러 개의 객체를 멤버로 지니고 있는 클래스를 상위객체 상위객체 안에 포함되어 있는 객체들을 하위클래스라 칭하겠다.) 여기서 상위 객체를 생성하는 과정에서 여러 개의 하위클래스의 생성자를 통해 하위객체를 초기화할 수 있다. 이것을 멤버 이니셜라이저를 이용한 멤버 초기화라 하는데 예시를 통하여 자세히 살펴보겠다.

 

Point.h
#ifndef __POINT_H_
#define __POINT_H_

class Point{
    private:
        int x;
        int y;

    public:
        Point(const int &xpos, const int &ypos);
        int GetX() const;
        int GetY() const;
        bool SetX(int xpos);
        bool SetY(int ypos);
};
#endif
Point.cpp
#include <iostream>
#include "Point.h"
using namespace std;

Point::Point(const int &xpos, const int &ypos){
    x=xpos;
    y=ypos;
}
int Point::GetX() const {   //const 함수
    return x;
}
int Point::GetY() const{
    return y;
}
bool Point::SetX(int xpos){
    if(0>xpos || xpos>100){
        cout<<"벗어난 범위의 값 전달"<<endl;
        return false;
    }
    x=xpos;
    return true;
}
bool Point::SetY(int ypos){
   if(0>ypos || ypos>100){
        cout<<"벗어난 범위의 값 전달"<<endl;
        return false;
    }
    y=ypos;
    return true;
}
Rectangle.h
#ifndef __RECTANGLE_H_
#define __RECTANGLE_H_

#include "Point.h"

class Rectangle{
    private:
        Point upLeft;
        Point lowRight;
    
    public:
        Rectangle(const int &x1, const int &y1, const int &x2, const int &y2);
        void ShowRecInfo() const;
};
#endif
Rectangle.cpp
#include <iostream>

#include "Rectangle.h"
#include "Point.h"
using namespace std;

Rectangle::Rectangle(const int &x1, const int &y1, const int &x2, const int &y2) 
    :upLeft(x1, y1), lowRight(x2, y2){		//멤버 이니셜라이저

}

void Rectangle::ShowRecInfo() const{
    cout<<"좌 하단: "<<'['<<upLeft.GetX()<<",";
    cout<<upLeft.GetY()<<']'<<endl;
    cout<<"우 하단: "<<'['<<lowRight.GetX()<<",";
    cout<<lowRight.GetY()<<']'<<endl<<endl;
}
RectangleConstructor.cpp
#include <iostream>
#include "Point.h"
#include "Rectangle.h"
#include "Point.cpp"
#include "Rectangle.cpp"
using namespace std;

int main(void){
    Rectangle rec(1, 1, 5, 5);
    rec.ShowRecInfo();
    return 0;
}
결과
좌 하단: [1,1]
우 하단: [5,5]

 

위의 코드 중 Rectangle.cpp를 살펴보면 :upLeft(x1, y1), lowRight(x2, y2) 이 부분이 바로 멤버 이니셜라이저이다. 이것이 의미하는 것은 객체 upLeft의 생성과정에서 x1과 y1을 인자로 전달받는 생성자를 호출하고 객체 lowRight의 생성과정에서 x2와 y2을 인자로 전달받는 생성자를 호출하라는 의미이다. 이렇듯 멤버이니셜라이저는 멤버변수로 선언된 객체의 생성자 호출에 활용된다.

 

멤버 이니셜라이저는 객체가 아닌 멤버의 초기화에도 사용할 수 있다. 예를 통해 살펴보겠다.

class SoSimple
{
private:
	int num1;
    int num2;
public:
   	SOSimple(int n1, int n2) : num1(n1)		//멤버이니셜라이저
    {
    	num2=n2;
    }
    .....
};

위의 클래스를 보면 멤버변수 num1을 이니셜라이저를 통해 초기화한 것을 알 수 있다. 따라서 프로그래머는 생성자의 몸체에서 초기화하는 방법과 이니셜라이저를 이용하는 초기화 방법 중에서 선택이 가능하다. 그러나 일반적으로는 멤버변수의 최기화에 있어서는 이니셜라이저를 선호한다. 왜냐하면 초기화의 대상을 명확히 인식할 수 있고 성능에 약간의 이점이 있기 때문이다.

 

  • 위의 코드처럼 이니셜라이저를 통해 보인 num(n1) 초기화는 int num1=n1; 과 같은 의미를 지닌다. 이니셜라이저를 통해서 초기화되는 멤버는 선언과 동시에 초기화가 이뤄지는 것과 같은 유형의 바이너리코드를 구성하기 때문이다.
  • 반면, 생성자의 몸체에서 보인 num2=n2; 초기화는 int num2; num2=n2; 두 문장과 같은 의미를 지닌다. 

즉, 이니셜라이저를 이용하면 선언과 동시에 초기화가 이뤄지는 형태로 바이너리 코드가 생성된다. 반면 생성자의 몸체 부분에서 대입연산을 통한 초기화를 진행하면, 선언과 초기화를 각각 별도의 문장에서 진행하는 형태로 바이너리 코드가 생성된다. 또한 const 변수와 참조차는 선언과 동시에 초기화해야 하기 때문에 이니셜라이저를 이용해야 한다.

 

 

 

'c++' 카테고리의 다른 글

[C++]this 포인터  (0) 2023.03.04
[C++]객체 배열과 객체 포인터 배열  (0) 2023.03.01
[C++]생성자(Constructor)와 소멸자(Destructor)  (0) 2023.02.25
[C++]캡슐화  (0) 2023.02.19
[C++] Const 함수  (0) 2023.02.18