클래스는 사용자가 정의한 추상적인 데이터형.
나밖에 모르는 타입이기 때문에 추상적이다.
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()
{
}
클래스 밖에 함수를 정의할 때는 스코프 연산자로 소속을 명시해준다.
MousePoint point;
클래스 (=타입) , 객체 (=변수)
void main()
{
MousePoint pt;
pt.x = 10;
pt.y = 20;
}
클래스는 구조체처럼 .을 이용해 변수에 직접접근 할 수 없다.
은닉된 데이터를 setXY라는 인터페이스로 접근해야한다.
void main()
{
MousePoint pt;
pt.SetXY(10, 20);
}
객체를 생성해서 캡슐화 된 데이터에 접근하는 것이 객체지향 프로그래밍의 기본이다.
void main()
{
MousePoint point;
point.x = 10;
}
'X' : cannot acess private member declared in class 'MousePoint'
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)
수많은 클래스 안에는 수많은 은닉화 된 데이터가 있고 그 데이터에 접근하기 위한 멤버 함수가 필요하다.
매번 초기화를 위한 멤버함수를 만들어 주어야 한다는 것은 여간 불편한 일이 아닐 수 없다.
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);
⇒ 초기화 할 때는 필요없지만, 값을 변경할 때는 사용!
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를 해주는 것처럼)
그런데 프레임워크를 사용하는 언어에서는 프레임워크에서 메모리 관리를 해주기 때문에 굳이 사용하지 않는다.