본문 바로가기
C++

[C++] 생성자, 초기화 리스트, 기본 생성자, 컴파일러가 하는 일, 생성자 오버로딩, 소멸자, const 멤버 함수, 구조체 vs 클래스

by imagineer_jinny 2022. 2. 14.

본 내용은 POCU COMP3200: C++ 언매니지드 프로그래밍 강의를 토대로 작성하였습니다.

 

 

  • 생성자 (Constructor)
    • 개체 처음 만들어질 때 호출되는 함수

 

  • 초기화 리스트 (Initializer List)
    • : 찍으면 초기화 리스트 시작한다는 것
    • 멤버 변수를 대입 없이 초기화
    • 상수나 참조 변수도 초기화 가능
    • 대입은 초기화가 된 이후에 실행되는 대입이고, 초기화 리스트는 오브젝트가 만들어질 때 초기화 하는 것
    •  
      기본적으로 초기화리스트 해줄 수 있는 것들은 해주는 것이 좋다. 
  • 기본 생성자
    • 기본 생성자는 매개변수를 받지 않음
      • 따라서 초기화를 자기가 알아서 해줘야 함
    • 클래스에 생성자가 없으면 컴파일러가 기본 생성자를 자동적으로 만들어 줌
    • 이렇게 자동적으로 만들어진 생성자는
      • 멤버 변수를 초기화하지 않음
      • 하지만 모든 포함된 개체의 생성자를 호출
      • Vector() { }

 

  • 컴파일러가 하는 일?
  • 사례1 - Vector 클래스에서 생성자가 없는 경우

컴파일러가 기본생성자 만들어줌. 근데 초기화 없이 빈 기본 생성자

 

  • 사례2 - Vector 클래스에 생성자가 있는 경우

매개변수 두개 받는 생성자가 있음.

이때는 생성자 안만들어줌. 이미 만들어져있으니까~

그래서 기본 생성자 쓰려고 하면 에러남

 

  • 둘 중 컴파일 안 되는 코드는?
    • 생성자가 아예 없으니까 컴파일러가 기본 생성자 만들어줌
      class Vector 
      { 
      private:
          int mX;
          int mY; 
      };
      
      void Foo() 
      { 
          Vector a;        // (1) OK
          Vector b(10, 2); // (2) 컴파일 에러
      }​
  • 둘 중 컴파일 안 되는 코드는?
class Vector
{
public:
    Vector(int x, int y);
private:
    int mX;
    int mY;
};

void Foo()
{
    Vector a;         // (1) 컴파일 에러
    Vector b(10, 2);  // (2) OK
}

 


* 오버 로딩 vs 오버 라이딩 (면접 출제!! 설명할 수 있을정도로 숙지하기)

  • 오버로딩(Overloading) : 함수 중복 정의
    • 오버로딩은 같은 이름의 함수에 매개변수를 다르게 사용하여 매개 변수에 따라 다른 함수가 실행되는 것 
      • 심화 설명
        1. 메소드 이름이 같아야 한다
        2. 리턴형이 같아도 되고 달라도 된다
        3. 파라미터 개수가 달라야 한다
        4. 파라미터 개수가 같을 경우, 자료형이 달라야 한다
  • 오버라이딩(Overriding) : 함수 재정의
    • 오버라이딩은 상속받았을 때 부모클래스의 함수를 사용하지 않고 다른 기능을 실행할 때 함수를 자식 클래스에 같은 이름, 매개변수로 재정의 해서 사용하는 것

  • 생성자 오버로딩(Overloading)
    • 여러 개의 생성자를 만들 수 있음
      • 같은 이름
      • 인자의 개수나 자료형은 다름
    • 기본 생성자
      • Vector() : mX(0), mY(0) { }
        Vector a; //기본 생성자 호출
    • 매개변수를 가지는 생성자
//2개의 매개변수를 가지는 생성자
Vector(int x, int y) : mX(x), mY(y)
{
}

Vector a(1,3); //매개변수 목록이 일치하는 생성자 호출

 

  • 소멸자(Destructor)
    • 객체가 지워질 때 호출됨
    • 가상 소멸자에 대해선 나중에 배워볼 것임
    • Java
      • 자동으로 가비지를 수집하기 때문에 소멸자 없음
    • C++
      • C++ 클래스는 그 안에서 동적으로 메모리를 할당할 수도 있음
      • 그런 경우 필히 소멸자에서 메모리를 직접 해제해줘야 한다
    • 소멸자에는 오버로딩이 없음. 왜? 자동으로 호출되기 때문에
    • 소멸자는 매개변수 없이 하나만 있다

 

  • 클래스 안에서의 동적 메모리 할당

Foo 영역은 스택에 있었으니까 사라지는데 힙에 있는 메모리가 힙에 남아있는 메모리 누수가 생김

 

할당을 했다면 반드시 지워주자! 

 

 

이제 메모리 릭 생기지 않는 모습

 

 

  • const 멤버 함수 : 면접 질문, 시험 문제 잘 나옴
    • Vector 클래스의 멤버 함수
    • const란?
      • 바꿀 수 없는 것을 말함

 

  • const 멤버 함수
    • 멤버 변수가 변하는 것을 방지
      const 안에서 아무것도 바꿀 수 없다고 했는데 바꾸려고 했으므로 컴파일 에러
  • 기본적으로 모든 함수는 const로 짜는게 맞고 멤버 함수 내에서 객체를 바꿀 때 그게 정말 필요하다면 const를 빼는게 맞음. 그래야 협업할 때 실수를 덜 함

 

코드 샘플

 

Vector2.h

#pragma once

class Vector2
{
public:
	Vector2();
	Vector2(int x, int y);
	
	int GetX() const;
	int GetY() const;
	void SetX(int x); //setter 메서드. 당연히 const가 없음
	void SetY(int Y); 

	void Add(const Vector2& vector);
	
private:
	int mX;
	int mY;
};

 

  • 구조체(Struct) vs 클래스(Class)
    • 기본 접근 권한
      • struct
        • public
      • class
        • private
    • C++엔 struct, class 둘 다 있음. 근데 컴퓨터는 이 둘을 구분할까? NOPE
    • 컴파일러는 이 둘을 구분할까? YES.
      • class는 private로 생각하고 접근을 막음 -> 컴파일 에러를 줌
      • 컴파일러는 차이점을 안다

 

  • 구조체에 관한 코딩 표준
    • C++에서는 구조체를 클래스처럼 쓸 수 있음
      • 하지만 절대 그러지 말 것
      • 구조체는 C 스타일로 쓰자
    • struct는 순수하게 데이터 뿐이여야 함 (Plain Old Data, POD) ex. int, float등
      • 사용자가 선언한 생성자나 소멸자 X
      • static 아닌 private/protected 멤버 변수 X
      • 가상 함수 X
      • 메모리 카피가 가능함
        • memcpy()를 사용하여 structchar[]로, 혹은 반대로 복사할 수 있음

댓글