<객체> 3. 클래스와 객체

정지민·2023년 9월 30일
0

객체 프로그래밍

목록 보기
3/11

객체 - 오브젝트
실체 - 인스턴스

클래스

  • 객체를 만들어내기 위해 정의된 설계도, 틀
  • 멤버 변수, 멤버 함수

클래스 선언부

  • class 키워드 통해 클래스 선언
  • 멤버 변수와 멤버 함수 선언
  • 접근권한 지정: private(디폴트), public, protected

클래스 구현부

  • 클래스에 정의된 모든 멤버 함수 구현

객체

  • 객체의 캡슐화: 객체를 캡슐로 싸서 그 내부를 보호하고 볼 수 없게 함
  • 객체의 일부분 공개: 외부와의 인터페이스를 통해 객체의 일부분 공개
  • 생성될때 클래스의 모양 그대로 가지고 탄생
  • 멤버 변수(상태), 멤버 함수(행동) 으로 구성
  • 실체라고 부름
  • 하나의 클래스에서 파생된 여러개의 객체 생성 가능
  • 객체들은 상호 별도의 메모리 공간에 생성

<예제 3-1> Circle 클래스의 객체 생성 및 활용

#include <iostream>
using namespace std; //이름 충돌 방지

class Circle {
public:                  //public으로 선언해주었음
	int radius;
	double getArea();

}; //Circle 선언부

double Circle::getArea() {
	return 3.14 * radius * radius;
} //Circle 구현부
 
int main() {
	Circle donut; //객체 donut 생성
	donut.radius = 1; //donut의 멤버 변수 접근
	double area = donut.getArea(); //donut의 멤버 함수 호출

	cout << "donut 면적은 " << area << endl;
	     
	Circle pizza;
	pizza.radius = 30;
	area = pizza.getArea();
	cout << "pizza 면적은 " << area << endl;
}

<예제 3-2> Rectangle 클래스 만들기

#include <iostream>
using namespace std;

class Rectangle {  //Rectangle 클래스 선언부
public:
	int width;
	int height;
	double getArea(); //면적을 계산하여 리턴하는 함수
};

double Rectangle::getArea() { //Rectangle 클래스 구현부
	return width * height;
}

int main() {
	Rectangle rect;
	rect.width = 3;
	rect.height = 5;
	cout << "사각형의 면적은 " << rect.getArea() << endl;
}

생성자

  • 객체가 생성되는 시점에서 자동으로 호출되는 멤버 함수
  • 클래스 이름과 생성자 이름은 동일
  • 목적: 객체가 생성될 때 필요한 초기화 위해
  • 리턴타입 x
  • 오직 한번만 호출, 자동 호출
  • 중복 가능, 그중 하나만 실행
  • 생성자가 선언되어있지 않으면 기본 생성자(매개변수 없음) 자동 생성

<예제 3-3> 2개의 생성자를 가진 Circle 클래스

#include <iostream>
using namespace std;

class Circle {
public:
	int radius;
	Circle(); //매개변수 없는 생성자
	Circle(int r); //매개변수 있는 생성자
	double getArea();
};

Circle::Circle() {
	radius = 1;
	cout << "반지름 " << radius << " 원 생성" << endl;
}

Circle::Circle(int r) {
	radius = r;
	cout << "반지름 " << radius << " 원 생성" << endl;
}

double Circle::getArea() {
	return 3.14 * radius * radius;
}

int main() {
	Circle donut; //매개 변수 없는 생성자 호출 -> Circle(); 자동호출
	double area = donut.getArea();
	cout << "donut 면적은 " << area << endl;

	Circle pizza(30); //매개 변수 있는 생성자 호출 -> Circle(30); 자동호출
	area = pizza.getArea();
	cout << "pizza 면적은 " << area << endl;
}

위임 생성자

  • 생성자가 다른 생성자를 호출
  • 코드 간소화
  • 타겟 생성자, 이를 호출하는 위임 생성자

다양한 생성자의 멤버 변수 초기화 방법

<예제 3-5> 멤버변수의 초기화와 위임 생성자 활용

Point::Point{x=0; y=0;}
Point::Point(int a, int b){x=a; y=b;}
    
//x,y를 생성자 서두에 초기값으로 초기화하고 위임 생성자를 이용
->

Point::Point():Point(0,0){	} //위임 생성자
Point::Point(int a, int b) //타겟 생성자
	:x(a), y(b){	}

기본 생성자

Q . 생성자는 꼭 있어야하는가? : 예

  • 매개변수 없다
  • 디폴트 생성자라고 부른다
class Circle{
	Circle(); //기본 생성자
}

클래스에 생성자가 하나도 선언되어 있지 않은 경우, 기본 생성자가 자동으로 생성된다

생성자가 하나라도 선언된 클래스의 경우, 기본 생성자를 자동으로 생성하지 않는다

<예제 3-6> Rectangle 클래스 만들기

#include <iostream>
using namespace std;

class Rectangle {
public:
	int width;
	int height;
	Rectangle();
	Rectangle(int w);
	Rectangle(int w,int h); //3개의 생성자가 필요함
	bool isSquare();
};
Rectangle::Rectangle() {
	height=width = 1;
	
}
Rectangle::Rectangle(int w) {
	height=width = w;
}
Rectangle::Rectangle(int w,int h) {
	width = w;
	height =h;
}

bool Rectangle::isSquare() {
	if (width == height) {
		return true;
	}
	else return false;
}

int main() {
	Rectangle rect1;
	Rectangle rect2(3, 5);
	Rectangle rect3(3);

	if (rect1.isSquare()) cout << "rect1은 정사각형이다." << endl;
	if (rect2.isSquare()) cout << "rect2은 정사각형이다." << endl;
	if (rect3.isSquare()) cout << "rect3은 정사각형이다." << endl;
}

소멸자

  • 객체가 소멸되는 시점에서 자동으로 호출되는 함수
  • 한번만 호출, 임의로 호출할 수 없음
  • 객체 메모리 소멸 직전 호출됨
  • 리턴타입 x, 매개변수 x
  • 오직 하나만 존재
  • 클래스 이름 앞에 ~ 붙임
  • 중복 불가능
  • 소멸자가 선언되어있지 않으면 기본 소멸자 자동 생성: 아무것도 하지 않고 자동 리턴
  • 객체는 생성의 반대순으로 소멸된다
class Circle{
	~Circle(); //소멸자 함수 선언
}

Circle::~Circle(){
}

<예제 3-7> Circle 클래스에 소멸자 작성 및 실행

생성자/소멸자 실행 순서

  • 지역 객체: 함수 내에 선언된 객체
  • 전역 객체: 함수 밖에 선언된 객체
  • 객체 생성 순서: 전역은 프로그램에 선언된 순서대로, 지역은 함수가 호출되는 순간에 생성
  • 객체 소멸 순서: 둘다 역순으로 소멸
  • new를 이용하여 동적으로 생성된 객체의 경우
    • new를 실행하는 순간 객체 생성, delete를 실행할때 객체 소멸

<예제 3-8> 지역 객체와 전역 객체의 생성 및 소멸 순서

-> 순서
프로그램 로딩 : (globalDonut, globalPizza)
main() 함수 시작 : (mainDonut, mainPizza)
f() 함수 실행 : (fDonut, fPizza)

접근지정자

  • 캡슐화(객체 보호, 보안) 가능
  • 중복 사용 가능

private(디폴트): 동일한 클래스의 멤버 함수에만 제한
public: 모든 다른 클래스에 허용
protected: 클래스 자신과 상속받은 자식 클래스에만 허용

멤버변수는 private 지정이 바람직함

오버헤드

인라인 함수

  • inline키워드로 선언
  • 인라인 함수를 호출하는 곳에 인라인 함수 코드를 확장 삽입, 인라인 함수 사라짐
  • 오버헤드 존재하지 않음, 실행 속도 개선
  • 단점: 전체 코드 크기 증가, 따라서 짧은 코드의 함수를 인라인 선언하는 것이 좋음

자동 인라인 함수

  • 클래스 선언부에 구현된 멤버 함수
  • inline으로 선언할 필요 없음
  • 생성자를 포함한 모든 함수가 자동 인라인 함수 가능

c++ 구조체

구조체와 클래스의 디폴트 접근 지정 비교


바람직한 c++ 프로그램 작성법

클래스 선언부: 헤더파일
클래스 구현부: cpp파일
main등 전역 함수나 변수는 다른 cpp파일에






0개의 댓글