본문 바로가기

BackEnd/C랑 C++

C++ 클래스 멤버변수 초기화를 알아보자

클래스를 사용할 때, 

클래스 안에 있는 멤버 변수에 대해서 초기화를 해줘야한다는 것은

잘 알고 있는데 여러가지 방법 중 어느 것을 써야할까? 에 대해서

다뤄보려고 한다

또 헷갈리는 일이 없도록 ~~

 

 

- 클래스 멤버 변수란

- 클래스 멤버 변수 초기화 방법 3가지


1. 클래스 멤버 변수 (Class Member Variable) 란

클래스 멤버 변수 초기화를 하려면, 먼저 멤버 변수를 알아야하니까

짧게 정리만 하려고 한다

 

위키백과 인용: 
객체 지향 프로그래밍에서 멤버 변수(member variable) 또는 멤버 필드는 특정 객체와 연결된 변수의 하나이며, 해당 변수의 모든 메소드(멤버 함수)에 접근이 가능하다. 클래스 기반 언어에서 이들은 두 종류로 구별된다: .....

 

그렇다.. 정의를 읽으면 알 수 있듯이 멤버 변수는

C++이나 Java 같은 객체 지향 프로그래밍에서 사용하는 개념으로

Class 안에 소속(?) 되어있는 친구이다

 

예시를 들어서 보도록 하겠다

 

#include <iostream>
using namespace std;

class initClass
{
    private:
        int var1;
        int var2;
        string str1;
};

 

initClass라는 클래스에

자료형이 int형인 var1, var2라는 멤버 변수와

자료형이 string인 str1이라는 멤버 변수가 정의되어 있는 것을 볼 수 있다

 

굳이 초기화를 해야하나....? 라는 생각을 할 수 있당

하지만 많은 사람들이 하라고 하는건 항상 이유가 있는거다

아래에서 짧게 다루겠다

 

 

1) 변수 초기화를 해야하는 이유

 

사실, 초기화를 해야하는 이유는 메모리 관점에서 다뤄야한다

하지만 눈에 안보이는 메모리보다..! 실제 찍히는 값을 봐야 와닿을 것 같아서

예시로 설명을 하려고 한다

 

#include <iostream>
using namespace std;

class initClass
{
    private:
        int var1;
        int var2;
        string str1;

    public:
        int getVar1() { return var1; }
        int setVar1(int var1) { this->var1 = var1; }

        int getVar2() { return var2; }
        string getStr1() { return str1; }
};

int main(void)
{
    initClass test;
    test.setVar1(10);

    cout << test.getVar1() << endl;
    cout << test.getVar2() << endl;
    cout << test.getStr1() << endl;

    return 0;
}

 

initClass라는 클래스의 멤버 변수인 var1, var2, str1에 대한 값을

출력해보는 예시이다

var1에 대해서만 10이라는 값으로 설정해주었다

 

실행시켜보면!!

 

10			/* int var1 */
32767			/* int var2 */
			/* string str1 */

 

값을 설정해주는 var1은 10으로 출력이 되었지만,,

아무 값도 없는 var2은 쓰레기 값을 뱉는다

string형인 str1은 " "을 출력한다

 

숫자 자료형은 이처럼 원하지 않는 값이 나오기 때문에

원하는 결과가 안나올 수도 있다

예를 들어,, 조건문을 사용해서 값 비교를 해서 이게 정상적인 경우인지!!

잘못된 경우인지!! 에 대해서 체크를 할텐데,

 

int main(void)
{
    initClass test;
    test.setVar1(10);

    cout << test.getVar1() << endl;
    cout << test.getVar2() << endl;
    cout << test.getStr1() << endl;

    if( test.getVar2() < 0 )
        cout << "var2는 잘못된 값" << endl;
    else
        cout << "var2는 정상인 값" << endl;

    return 0;
}

 

숫자형 값에 대해 유효성을 따질 때, 요런식으로 비교할텐데

var2에 대해 수 초기화를 하지 않으면 무슨 값으로 나올지 모르기 때문

초기화는 습관적으로 해주는 것이 좋다

(클래스 멤버변수를 예로 들었지만, 일반적으로 사용하는 변수들도 당연히 해줘야한다)

 

그러면 다시 본론으로 돌아와서, 클래쓰 멤버 변수를 초기화하는 방법을 정리해보겠당

 


2. 클래스 멤버 변수 초기화 방법 3가지

멤버 변수 초기화 방법에는 3가지가 있다 (더 있을 수도 있음)

 

1) 멤버변수 정의시 초기화 하기 

2) 생성자에서 초기화 하기

3) 생성자에서 초기화 리스트로 초기화 하기

 

하나씩 예를 보면서 정리하겠다

 

1) 멤버변수 정의시 초기화 하기 

 

요 방법은 우리가 보통 변수에 값을 넣는 방법과 동일하다

 

int var1 = 10;

 

요거를 클래쓰 안에서 멤버 변수 정의할 때 똑같이 써주면 된다 ^0^/

 

class initClass
{
    private:
        int var1 = 10;
};

 

이렇게 말이다 너무 간단해서 할말을 잃었다

 

 

2) 생성자에서 초기화 하기

 

두번째 방법은 생성자에서 값을 초기화 해주는 것이다

 

class initClass
{
    private:
        int var1 = 10;
        int var2;
        string str1;

    public:
        initClass()
        {
            var1 = 10;
        }
};

 

생성자 안에서 클래스 멤버 변수에 값을 직접 초기화할 수 있고,

위에 예시는 기본 생성자로 초기화를 했는데

파라미터가 다른 생성자를 오버로딩(Overloading)해서 값을 받아 초기화할 수도 있다

 

class initClass
{
    private:
        int var1 = 10;
        int var2;
        string str1;

    public:
        /* Default 생성자*/
        initClass()
        {
            var1 = 10;
        }
	/* Overloading 한 생성자*/
        initClass(int var)
        {
            var1 = var;
        }
};

int main(void)
{
    initClass test(10);
}

 

이런식으로 말이다

그리고 생성자에서 초기화 하는 방법이 하나 더 있는데

그것은 바로 ↓

 

 

3) 생성자에서 초기화 리스트로 초기화 하기

 

바로... 초기화 리스트 (Member Initialize List == 멤버이니셜라이즈) 라는 것을

사용해서 초기화 할 수 있다

말 그대로 초기화를 리스트로 여러개~~ 하는거고,

사용법은 생성자 함수 옆에 콜론(:)을 붙여서 사용하면 된다

 

initClass(int v1, int v2) : var1(v1), var2(v2) {}

 

이렇게!! 멤버 변수에 괄호를 통해 파라미터로 받은 값을 대입해주는 모양이다

앞에서본 생성자 형식과 비교를 해보면

 

/* 1. Default 생성자 */
initClass()
{
	var1 = 10;
}
/* 2. 생성자 오버로딩, 값 정의 */
initClass(int var)
{
	var1 = var;
}
/* 3. 생성자 오버로딩, 초기화 리스트 사용 */
initClass(int v1, int v2) : var1(v1), var2(v2)
{}

 

요렇게 되시겠다.

멤버 초기화 리스트 사용

이렇게 멤버 변수를 초기화하는 것뿐만 아니라

상속 받은 클래스의 경우 부모 클래스의 멤버 변수를 초기화 하거나

복잡할 수 있는 레퍼런스(Reference) 변수 초기화에도 유용하다

 

멤버 변수가 많다면, 초기화 리스트도  엄청 길어지기도 한다 -_-a

 

 

2-1. 그래서 뭘 사용해야하는데

 

뭘 사용해도 사실 상관 없다!

하지만 복합적으로 사용할 때도 있을 수 있으니, 초기화 3가지 방법의

순서만 알고 넘어가자

 

직접해보는 것이 제일이다

 

* 코드

#include <iostream>
using namespace std;

class initClass
{
    private:
        int var1 = myPrint(10, "멤버변수정의");

    public:
        initClass() : var1(myPrint(30, "초기화 리스트"))
        {
            var1 = myPrint(20, "생성자에서 초기화");
        }

    public:
        int getVar1() { return var1; }
        int myPrint(int ret, string str)
        {
            cout << ret << ", "<< str << endl;
            return ret;
        }
};

int main(void)
{
    initClass test;
    cout << test.getVar1() << endl;

    return 0;
}

 

* 실행 결과

30, 초기화 리스트
20, 생성자에서 초기화
20

 

짜잔.. 정리해보자면

 

- 초기화 우선순위: 초기화 리스트 > 생성자에서 초기화

 

이렇게 되고,

위 예시에서는 멤버변수 정의는 호출이 안되어서

초기화 리스트를 지우고! 한번더 테스트 ㄱㄱ

 

* 코드

class initClass
{
    private:
        int var1 = myPrint(10, "멤버변수정의");

    public:
        initClass()
        {
            var1 = myPrint(20, "생성자에서 초기화");
        }
};

 

* 실행 결과

10, 멤버변수정의
20, 생성자에서 초기화

 

그렇다... 

- 초기화 우선순위: 초기화 리스트 > 멤버 변수 정의시 초기화 > 생성자에서 초기화

 

요렇게 되시겠다 ^^7

최종으로 초기화 되는 값은 마지막 우선순위 방법으로 될테니까

주의하자

 

 


* 위키 백과 - 멤버 변수

ko.wikipedia.org/wiki/%EB%A9%A4%EB%B2%84_%EB%B3%80%EC%88%98

 

멤버 변수 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전.

ko.wikipedia.org