본문 바로가기

C++/FOCU_C++

C++ chpt6.

개체지향 프로그래밍(OOP: Object-Orieted Programming)

JAVA vs C++

 

JAVA

  • 클래스
  • 개체
  • 생성자
  • 함수 오버로딩
  • 힙에 개체 생성하기

C++

  • 클래스
  • 개체
  • 생성자
  • 함수 오버로딩
  • 힙에 개체 생성하기
  • 스택에  개체 생성하기
  • 복사 생성자
  • 소멸자
  • 연산자 오버로딩

C++ 에서는 OOP 와 OOP 가 아닌 것을 섞어 쓸 수 있음 (C 와의 호환성)

C++ 은 언매니지드 언어이기 때문에 매니지드언어인 JAVA 에 없는 특별한 기능이 많음

 

 

OOP 란 뭘까?

  • '사람들이 세상을 바라보는 방식' <= OOP 의 핵심
  • 직관적

다음 이미지는 '사람' 을 예시로 들 때, 사람이 가지는 데이터나 행위에 대해 예를 든 것이다

위 예시를 아래처럼 코드화하는 것이 OOP 의 방식이다.

// JAVA 클래스
public class Human
{
    private string name;
    private sex;
    private age;

    public void eat();
    public void walk();
    public void talk();
}

Human student = new Human();
Human teacher = new Human();

복잡하게 구현된 OOP

  • 닷컴버블 시절
  • 일부 객체지향 분석과 디자인(OOAD)
  • 일부 디자인 패턴들

예) 개체 A 가 개체 B 를 통해 숫자를 증가시키는 과정

 

해당 방식은 오브젝트를 직접 수정하는 것이 아닌 오브젝트가 포함된 다른 오브젝트를 만듬으로써,

오브젝트의 크기를 계속 키우는 방식을 사용함

(오브젝트를 직접 수정하는 것이 오류를 더 많이 발생할 것이라는 생각에 기초)

 

 

위를 직관적 OOP 로 수정한다면

 

이렇게 간단하게 구성할 수 있다.

 


접근제어자(Access Modifier)

 

클래스(class)

 

Vector 클래스 구상해보기(JAVA 코드 활용)

// JAVA
public class Vector
{
    int x;	// this 를 통해 멤버 변수 사용
    int y;
}
------------------------------------------
// C++ (위의 JAVA 코드를 그대로 가져왔을 경우의 코드)
class Vector
{
    int mX;	// 최근 멤버의 m 을 붙혀서 변수를 사용하는 쪽으로 지향
    int mY;
};
// 이런 코드 스타일은 권장하지 않음 (멤버 변수 내용 제외)

 

멤버 변수의 접근

 

C++ 의 기본 접근 권한은 'Private'

class Vector
{
    int mX;	// private
    int mY;	// private
};

 

자바에선 접근권한 제어 키워드를 생략하면 public 도 private 도 아닌 상태가 됨

  • 해당 변수는 패키지 내에서 접근가능
  • 오브젝트를 다른 곳에서 마음대로 접근 가능
  • C++ 의 fried 기능처럼 사용하려고?

 

접근제어자

  • public
    • 누구나 접근 가능
  • protected
    • 자식 클래스에서 접근 가능
  • private
    • 해당 클래스에서만 접근 가능(개체에서가 아님, 클래스 단위)

 

보통 제어자별로 C++ 멤버들을 그룹 지어서 프로그래밍함

class SomeClass
{
public:
    int PubliMember;
protected:
    int mProtectedMember;
private:
    int mPrivateMember1;
    int mPrivateMember2;
};

개체 생성(오브젝트 인스턴스 생성)

// C++
// 스택 메모리에 만들기 (빠름)
Vector a;

// 힙 메모리에 만들기 (느림)
Vector *b = new bector();

-------------------------------------------------
// JAVA
// 스택 메모리에 만들 수 없음

// 힙 메모리에 만들기 (느림)
Vector a = new Vector();

 

Vector a 의 구조

 

  • 스택에 메모리 할당
  • int x, y (4바이트씩 총 8바이트 멤버 크기 보유)

 

Vector *b = new Vector() 의 구조

  • 힙에 메모리 할당


스택(Stack)

  • 예약된 로컬 메모리 공간(작음, 일반적으로 1MB 이하) - 컴파일 과정에서 확인 후 할당
  • 함수 호출과 반환이 이 메모리에서 일어남
  • 단순히 스택 포인터를 옮김
    • 메모리를 할당 및 해제할 필요가 없음
    • 스택에 할당된 메모리는 범위(scope)를 벗어나면 사라짐
    • 변수와 매개변수를 위해 필요한 크기는 컴파일 도중에 알 수 있음
  • but! 스택에 큰 개체를 많이 넣을시
    • 스택 오버플로우가 발생할 수 있음
    • 성능이 느려질 수 있음(OS 단위에서의 표현)

스택에 1MB 공간을 프로그램 실행시 한 번에 고정 시키는 것이 아닌 필요한 만큼은 사용하고,

나머지는 하드웨어에 swap 파일(페이징) 형태로 남아 있다가, 필요시 하드에서 읽어와서 사용함

 

힙(Heap)

  • 전역 메모리 공간(크고, ~GBs 단위)
  • 비어있는 채로 존재하며, 연속된 메모리 블록을 찾아야 함
  • 프로그래머가 메모리를 직접 할당 및 해제해야 함
    • 직접 하지 않을 시 메모리 누수가 발생
    • 언매니지드 언어의 특성

프로그램 작성시 스택을 활용할 수 있다면 가능한한 스택을 사용하는 게 유리, 

실행 도중 새로 만들거나, 한 함수 스코프 안에서 끝나지 않고 여러 곳에 전달되는 경우엔 힙을 쓰는 것이 좋음

또한 반환하는 오브젝트 크기가 크다면, 힙으로 생성해서 주소만 던져주는 방식도 도움이 됨

 

 

스택 활용 코드를 통해 스택을 살펴보기

Vector AddVector(const Vector& a, const Vector& b) // const 참조를 통해 해당 파라미터의 값이 바뀌는 것을 방지
{
    Vector result;
    result.mX = a.mX + b.mX;
    result.mY = a.mY + b.mY;

    return result;
}

void Foo()
{
    Vector c = AddVector(a, b);
}

 

해당 코드의 스택 변화

 

 

 

힙 활용 코드를 통해 힙을 살펴보기

Vector PrintVector(const Vector& a, const Vector& b) // const 참조를 통해 해당 파라미터의 값이 바뀌는 것을 방지
{
    Vector result = new Vector;	// 함수 내부에서 new 를 사용하는 건 좋은 예시는 아님
    result.mX = a.mX + b.mX;
    result.mY = a.mY + b.mY;

    // 출력 ...
}

void Foo()
{
    PrintVectors(a, b);
}

 

해당 코드의 힙 변화 (delete 가 없는 것을 고려해서 변화 확인)

 

delete 를 사용하지 않아 함수는 끝났음에도 불구하고 heap 메모리가 사용중인 채로 잡혀있음

아래와 같이 delete 를 사용해줌으로써, 해당 영역을 해제하여야 다른 곳에서 필요시 다시 사용할 수 있음

Vector PrintVector(const Vector& a, const Vector& b) // const 참조를 통해 해당 파라미터의 값이 바뀌는 것을 방지
{
    Vector result = new Vector;	// 함수 내부에서 new 를 사용하는 건 좋은 예시는 아님
    result.mX = a.mX + b.mX;
    result.mY = a.mY + b.mY;

    // 출력 ...
    
    delete result;	// delete 를 통해서 사용한 힙 영역 해제
}

void Foo()
{
    PrintVectors(a, b);
}

 

C++에서는 함수 내 new 사용을 '지양'하는 것을 권장, 현대 C++에서는 RAII 원칙에 따라 자동 자원 관리를 우선시하기 때문임
메모리 누수, 예외 안전성 부족, 소유권 불명확 등의 문제가 발생하는 것을 방지하고자 하는 방향임
대신 스마트 포인터(std::unique_ptr 등)표준 컨테이너(std::vector 등)를 사용하는 것이 안전

(RAII: Resource Acquisition Is Initialization)


개체 배열(Array)

// JAVA
Vector[] list = new Vector[10]; 
// 벡터 레퍼런스로 10개 담을 '공간을 NULL 로 할당'(벡터 생성은 별도로 다시 작업해줘야 됨)

--------------------------------------------------------------------------
// C++
Vector *list = new Vector
// 벡터 10개 생성

 

두 벡터 생성의 차이를 그림으로 설명한다면 다음과 같다

C++
// 10개의 '벡터 개체'를 힙에 생성
Vector *list = new Vector[10];

// 10 개의 '포인터'를 힙에 생성
Vector **list = new *Vector[10];

-------------------------------------------
JAVA
// 10 개의 '벡터 개체'를 힙에 생성

불가능

// 10 개의 '포인터'를 힙에 생성
Vector[] a = new Vector[10];

개체 소멸

// JAVA
Vector a = new Vector();

// ...

// 가비지 컬렉터를 통한 메모리 해제, 메모리 할당을 즉시 해제하지 않음
a = NULL;
---------------------------------------------------------
// C++
Vector *a = new Vector;
Vector *list = new Vector[10];

// ...

delete a; // 직접 호출, 메모리 즉시 해제
a = NULL; // 미재사용시 생략가능, 재사용시 실수 방지 차원에서 기입

delete [] list; // [] 를 반드시 입력!!
list = NULL; // 미재사용시 생략가능, 재사용시 실수 방지 차원에서 기입

 

new 를 한 뒤에는 반드시 delete 를 사용!!!!


멤버 변수 초기화

// JAVA
public class Vector
{
    private int x;
    private int y;
}

Vector a = new Vector();
// a 의 멤버 변수 x 와 y 는 0 으로 초기화

---------------------------------------
// C++
class Vector
{
public:
	int mX;
    int mY;
};

Vector a;
Vector *b = new Vector();
// 따로 설정을 해주지 않으면 a 나 b 의 멤버 변수 mX, mY 는 쓰레기 값을 가짐

 

JAVA 와 C# 은 0으로 초기화시켜줌

 

C++ 은 초기화 작업이 없음

  • 성능을 위해서

JAVA 의 초기화

  • 어떤 자료형에서도 동일하게 적용
    • string str; = null 의 비트패턴은 전부 0 이므로 null
    • float f; = 0.0 의 비트패턴은 전부 0 이므로 0.0
    • int i; = 0 의 비트패턴은 전부 0 이므로 0

만일 C 에 없는 기능이 다른 언어에 있다면

  • 컴퓨터가 알지 못하는 것
  • 다른 엔지니어가 구현한 것
  • 해당 기능을 구현한 부분에 대해서 배움의 자세를 가져야 함

 

 

'C++ > FOCU_C++' 카테고리의 다른 글

C++ chpt8.  (1) 2025.07.21
C++ chpt7.  (2) 2025.07.01
C++ chpt5.  (0) 2025.05.04
C++ chpt4.  (0) 2025.05.03
C++ chtp3.  (0) 2025.05.03