220907 C++ #2

김혜진·2022년 9월 7일
0

C++

목록 보기
2/12

C++ #2

클래스

클래스는 사용자가 정의한 추상적인 데이터형.
나밖에 모르는 타입이기 때문에 추상적이다.
int , double은 구체적인 데이터형.

캡슐화

class MousePoint
{
	int x;
    int y;
    // 멤버 변수 (외부 노출 X)
    
    void setXY(int x, int y) // 멤버 함수, 인터페이스(외부 노출 O)
    {
    }
}

접근지정자

class MousePoint
{
private: // 외부 접근 불가능
	int x;
    int y;

public: // 외부 접근 가능
    void setXY(int x, int y)
    {
    }
}

기본적으로 데이터는 은닉화(캡슐화) 되어야 한다.
대부분의 멤버 변수는 private, 멤버 함수는 public을 사용한다.

멤버 함수 사용

  • 멤버 함수 정의 시 어느 클래스 소속인지 밝혀야 하므로 함수의 이름 앞에 클래스명을 기술한다.
  • 클래스 명과 함수 이름 사이에 스코프 연산자(::)를 기술한다.

C,C++은 함수의 원형과 함수의 정의로 나누어진다.

  • 함수의 원형
void SetXY();
  • 함수의 정의
void SetXY()
{
}
#include <iostream>

class MousePoint
{
private:
	int x;
	int y;

public:
	void SetXY(int nX, int nY); // 함수의 원형

};

void MousePoint::SetXY(int nX, int nY) // 함수의 정의
{
	x = nX;
	y = nY;
}

void main()
{

}

클래스 밖에 함수를 정의할 때는 스코프 연산자로 소속을 명시해준다.

객체 생성

  • 클래스 데이터형도 int, char, double과 같은 기본 자료형을 선언하듯이 선언하면 된다.
  • 클래스를 통해 선언한 변수를 객체라고 한다.
MousePoint point;

클래스 (=타입) , 객체 (=변수)

void main()
{
	MousePoint pt;
	pt.x = 10;
	pt.y = 20;
}

클래스는 구조체처럼 .을 이용해 변수에 직접접근 할 수 없다.
은닉된 데이터를 setXY라는 인터페이스로 접근해야한다.

void main()
{
	MousePoint pt;
	pt.SetXY(10, 20);
}

객체를 생성해서 캡슐화 된 데이터에 접근하는 것이 객체지향 프로그래밍의 기본이다.


멤버 접근(멤버변수 및 멤버함수)

  • 코드 작성

멤버 변수

  • MousePoint 클래스에 선언된 x, y 값이 바로 멤버 변수이다.
  • 객체 지향 철학에 의해 멤버 변수는 은닉화 된다.
  • 멤버 함수를 통해서만 멤버 변수 접근이 가능하다.
void main()
{
	MousePoint point;
    point.x = 10;
}

'X' : cannot acess private member declared in class 'MousePoint'

멤버 함수

  • MousePoint클래스에 선언된 SetXY 함수가 바로 멤버 함수이다.
  • 멤버 변수의 접근은 오직 멤버 함수를 통해서만 이루어져야 한다.
  • 멤버 함수는 멤버 변수를 컨트롤 할 수 있는 유일한 게이트다.


생성자

초기화란

  • 초기화란 기본 데이터를 선언과 동시에 초기값을 대입하는 것이다.
int a = 5;
float b = 10.5;
int c[5] = {1,2,3,4,5}
  • 변수 선언 후에 값의 할당이 이루어진다면 초기화라고 할 수 없다.
int a;
a = 5;

구조체의 멤버 초기화

구조체와 클래스는 닮은 점이 참 많다.

  • 구조체 초기화
#include <iostream>

struct MousePoint
{
	int x;
    int y;
}

void main()
{
	MousePoint point = {10,20};
}

❗ 구조체를 클래스로 변형해 초기화 하는 방법

1. 접근 지정자를 private에서 public으로 변경 (객체지향의 철학인 캡슐화에 위배됨)

2.멤버 변수 x, y의 접근을 위한 멤버 함수의 구현
멤버 변수 x, y의 초기화를 위한 멤버 함수의 구현

  • 클래스 초기화
#include <iostream>
using namespace std;

class MousePoint
{
private:
	int x;
	int y;

public:
	int getX();
	int getY();
	void SetXY(int nX, int nY);
};

int MousePoint::getX() 
{
	return x;
}

int MousePoint::getY()
{
	return y;
}

void MousePoint::SetXY(int nX, int nY)
{
	x = nX;
	y = nY;
}

void main()
{
	MousePoint pt;
	pt.SetXY(10, 20);
	cout << "x좌표 : " << pt.getX() << endl;
	cout << "y좌표 : " << pt.getY() << endl;

}

클래스는 private을 지정해주지 않아도 private로 인식을 한다. (구조체는 public)

생성자의 필요 이유

  • 클래스 생성 시 매번 반복되는 초기화 멤버 함수를 만들어야 한다.
  • 객체 생성 시 자동으로 초기화 해주는 초기화 전용함수가 제공되는데, 이 함수를 생성자(constructor)라고 한다.

수많은 클래스 안에는 수많은 은닉화 된 데이터가 있고 그 데이터에 접근하기 위한 멤버 함수가 필요하다.
매번 초기화를 위한 멤버함수를 만들어 주어야 한다는 것은 여간 불편한 일이 아닐 수 없다.

생성자의 특징

  • 생성자의 이름은 클래스의 이름과 동일
  • 생성자의 타입은 지정하지 않음
  • 생성자의 호출은 객체 선언 시 자동으로 호출. 인위적 호출 안됨
  • 반환값을 지정하지 않음
  • 디폴트 생성자가 존재

생성자의 형태

  • 생성자 이름은 클래스와 동일하고 생성자의 타입 또한 없으며 반환 값도 없다.
 MousePoint::MousePoint()
{
	x = 0;
	y = 0;
}

리턴 타입이 없으므로 리턴 사용 X
전달인자가 필요하다면 안 써도 됨
"생성자는 객체의 초기화를 위해 존재한다."

  • 명시적인 호출이 아니라 객체 선언 시 자동 호출
  • 객체 생성 시 값을 전달하기 위한 실 매개변수 값을 추가
MousePoint pt(50,100);

pt라는 객체가 생성될 때, 전달인자의 개수를 보고 자동으로 호출해 초기화한다.

#include <iostream>
using namespace std;

class MousePoint
{
private:
	int x;
	int y;

public:
	int getX();
	int getY();
	void SetXY(int nX, int nY);
	MousePoint(int nX, int nY); // 생성자
};

int MousePoint::getX()
{
	return x;
}

int MousePoint::getY()
{
	return y;
}

void MousePoint::SetXY(int nX, int nY)
{
	x = nX;
	y = nY;
}

// 생성자
MousePoint::MousePoint(int nX, int nY)
{
	x = nX;
	y = nY;
}

void main()
{
	MousePoint pt(10,20);
	cout << "x좌표 : " << pt.getX() << endl;
	cout << "y좌표 : " << pt.getY() << endl;
}

전달인자가 없다면 전달인자 없이 객체만 생성한다.

MousePoint pt;

생성자를 작성하지 않아도 디폴트 생성자가 호출된다.
모든 클래스는 디폴트 생성자가 내장되어있다.
pt는 함수가 아닌 변수다.

pt.SetXY(10, 20); ⇒ 초기화 할 때는 필요없지만, 값을 변경할 때는 사용!

디폴트 생성자

  • 앞의 생성자는 매개변수 2개를 가지고 있었다.
    만약 전달인자를 넘겨주지 않고, 객체를 선언한다면?
MousePoint pt;

다음과 같은 컴파일 에러 발생
'MousePoint' : no appropriate default constructor available

메시지의 의미는 사용할 수 있는 디폴트 생성자가 없다는 것이다.
생성자를 명시적으로 정의하지 않더라도 생성자를 호출?
C++에서는 디폴트 생성자의 지원 기능을 제공

  • 디폴트 생성자의 형태
MousePoint::MousePoint()
{
}

코드에 생성자가 명시되지 않았을 때는 따로 작성해주지 않아도 디폴트 생성자가 내부에서 동작을 하지만, 전달인자를 가진 생성자가 명시되면 디폴트 생성자도 작성을 해주어야 한다.

생성자 오버로딩

MousePoint::MousePoint(int nX, int nY)
{
	x = nX;
	y = nY;
}

MousePoint::MousePoint()
{
	x = 0;
	y = 0;
}

소멸자

객체가 소멸할 때 자동 호출되는 소멸자(Destructor)가 존재한다.

소멸자의 특징

  • 소멸자도 클래스의 이름을 그대로 사용한다. 맨 앞에 틸트(~) 기호 표기
  • 소명자의 타입 지정 안함
  • 객체 소멸 시 자동 호출. 인위적 호출 금지
  • 반환값을 지정하지 않음
  • 전달인자 지정 안함
  • 소멸자는 생성자처럼 오버로딩 안됨
#include <iostream>
using namespace std;

class MousePoint
{
private:
	int x;
	int y;

public:
	int getX();
	int getY();
	void SetXY(int nX, int nY);
	MousePoint(int nX, int nY); // 생성자
	MousePoint(); // 디폴트 생성자
	~MousePoint(); // 소멸자
};

int MousePoint::getX()
{
	return x;
}

int MousePoint::getY()
{
	return y;
}


void MousePoint::SetXY(int nX, int nY)
{
	x = nX;
	y = nY;
}

// 생성자
MousePoint::MousePoint(int nX, int nY)
{
	x = nX;
	y = nY;
}

// 디폴트 생성자
MousePoint::MousePoint()
{
	x = 0;
	y = 0;
}

// 소멸자
MousePoint::~MousePoint()
{
	cout << "소멸자 호출" << endl;
}


void main()
{
	MousePoint pt1;
	cout << "x좌표 : " << pt1.getX() << endl;
	cout << "y좌표 : " << pt1.getY() << endl;

	MousePoint pt2(100, 200);
	cout << "x좌표 : " << pt2.getX() << endl;
	cout << "y좌표 : " << pt2.getY() << endl;
}

동적 메모리 할당이 아니므로 스택 영역에 데이터가 쌓여 pt2부터 소멸됨!

객체가 생성되면 생성자와 소멸자를 자동호출한다.
(동적으로 메모리를 할당 했을 때 free를 해주는 것처럼)
그런데 프레임워크를 사용하는 언어에서는 프레임워크에서 메모리 관리를 해주기 때문에 굳이 사용하지 않는다.

profile
알고 쓰자!

0개의 댓글