프로그래밍 언어/C & C++ 정리

Java와 C++ 로 비교하는 - 초기화 리스트와 기본 생성자

뽀또치즈맛 2024. 10. 31. 11:05

 

 

대입의 개념과 초기화 리스트의 차이

//Java

class Vector
{
	public:
    vector()
    {
    //이건 대입
    	mX = 0;
        mY = 0
    }
}

/C++

class Vector
{
public :
	vector();
    //이건 초기화
    	: mX(0),mY(0)
        {}
}

 

 

실제 코드 상에서는 대입과 초기화 리스트가 차이가 없어보인다.

근데 초기화 해야하는 이유는

대입은 초기화가 된 이후에 실행되는 애이고,

초기화 리스트는 실제 오브젝트가 만들어질 때 초기화하는 것이다.

 

초기화 리스트를 권장하는 이유는 다음과 같다.

특히 멤버 변수를 대입 없이 초기화 할 수 있으며

상수나 참조 변수도 초기화가 가능하다.

 

다음과 같이 const나 참조는 선언 이후에 대입할 수 없다.

const는 한 번 대입되면, 한 번 초기화하면 바꿀 수 없는 값이며

참조는 처음 만들 때 누구를 가리키는지 정의가 되어야 한다.

 

// C++ 초기화 리스트 허용 가능

class X
{
	const in mNameSize;
    AnotherClass& mAnother;
    
    X(AnotherClass& another) : mNameSize(20), mAnother(another) {}
}

// C++ const와 참조자 선언 후 대입

class X
{
	const in mNameSize;
    AnotherClass& mAnother;
    
    X(AnotherClass& another) : {
    	mNameSize = 20;		// 에러
        mAnother = another;	// 에러
    }
}

 

그래서 여기서 초기화 리스트를 하면 허용이 된다.

하지만 대입을 하게되면

너 왜 const인데 왜 바꿔? 너 참조자 생성할 때 다 초기화 했잖아 근데 왜 바꿔?

우리 약속했잖아 안돼; 하면서 허용하지 않는다.

그럼 이제 애러가 나게된다.

 

이런 간단한 것도 헷갈리는 것이라면 C++가 숙련되지 않는 것이다.

이는 기본 중에 기본이니, 초기화와 대입을 꼭 구분해자.

 

기본적으로 초기화 할 수 있는 것은 다 초기화해서 사용하도록 하자.

 

그럼 다음과 같은 코드는 왜 이렇게 쓸까?

Vector::Vector() : mX(0), mY(0)
{
}

 

0을 안넣어주면 쓰레기 값이 나오기 때문에 위험한 경우가 많으니까

그냥 Vector만들어주면 0,0이라고 프로그래머가 결정해주는 것이다.

 

이러한 것은 개인의 선택이지만,

다른 언어와 같이 컴파일러가 직접 개입하여 초기화해주지 않는다는 것을 기억해야 한다.

 

 

기본 생성자

 

기본 생성자는 매개변수를 받지 않는다.

 

(기본 생성자 & 아무 생성자도 만들지 않을 때)

클래스에 생성자가 없으면 컴파일러가 기본 생성자를 자동적으로 만들어 준다.

 

이렇게 자동적으로 만들어진 생성자는

1. 멤버 변수를 초기화하지 않는다.

2. 하지만 모든 포함된 개체의 생성자를 호출해준다.

-> 이는 Java하고 다르다.

 

Java는 모든 것이 레퍼런스니까, 

초기화해줄 때 어떤 개체의 레퍼런스를 들고 있다면

순수하게 nullptr로 초기화 해주면 된다.

 

 

C++는 그렇게 포인터로 참조를 가지고 있는 거 외에도

어떤 개체 안에 다른 개체를 가지고 있을 수 있다. (찐 기본 개체를 소유)

그러면 C++ 언어에서는 개체의 생성자를 호출해준다.

그래서 오브젝트를 쓰면 좋은 점이 이러한 부분이다.

 

그렇다면 Vector 클래스에 생성자가 있는 경우는 어떨까?

안만들어준다.

 

왜냐, 니가 생성자 만들어줬으면

니가 하려던 목적을 이루면 되는 거 같은데

내가 기본적으로 생성자를 만들어 줄 필요가 없지?

필요하면 프로그래머 니가 만들어 썼겠지? 하고 기본생성자가 없다.

 

즉 기본 생성자가 없는 것이 너의 의도라는 것임을 알겠다!

하고 obj 를 만들어주는 것이다.

 

 

class Vector
{
private:
	int mX, mY;
}


void Foo()
{
    Vector a;
    Vector b(10,2);		
}

 

 

 

그럼 이런 경우는 어떤 에러가 날까?

당연히 b가 애러뜬다.

왜냐면 int값 2개 받아오는 생성자를 만들어준 적이 없으니

의도한 바라고 판단하고 컴파일에서 에러가 뜨는 것이다.

 

생성자 오버로딩 (Overloading)

여러 개의 생성자를 만들 수 있다는 것이다.

 

오버로딩이란?

- 같은 이름이다.

- 인자의 개수나 자료형은 다르다.

 

이는 OOP의 다형성에 속하는 특징이다.

오버로딩과 오버라이딩은 당연히 차이가 있으며,

C++ 사용자라면,

이를 잘 설명할 수 있을 정도로 숙지해놔야 한다.

 

아래 두 코드 둘 다 에러가 나지 않는다고 가정해보자.

Vector() : mX(0), mY(0) {}
Vector a; // 기본 생성자 호출

 

그럼 이름이 같은 생성자이지만, 인자의 개수가 다른 생성자 2개가 있는 것이다.