[C++] 객체지향 개념(객체/클래스/생성자) 및 헤더파일 분리 요약정리

★Object Oriented Programming★

 

ㅁ 객체지향 언어

추상화, 캡슐화, 상속, 다형성을 사용하여 유연성과 모듈성, 명료함 재사용성을 제공하는 부가된 특징을 가지고 있는 강력한 절차형 언어

- 모든 객체의 속성과 행동을 결합시킴으로써 실제 세계를 반영하는 방법으로 프로그램 구성

- 객체의 관점에서 생각하고, 프로그램은 상호작용하는 객체들의 모임으로 볼 수 있음

 

 

ㅁ 객체

명확히 확인이 가능한 실제 세계에서의 존재물을 대표하는 것. 책상, 원, 대여 등

- 객체는 자신만의 특성과 상태, 행동을 갖는다.

 * 상태(정적) : 현재 값을 가지고 있는 데이터 필드(= 속성)에 의해 표현됨 → 변수

 * 행동(동적) : 일련의 함수에 의해 정의된다. 객체에 대한 함수를 호출하는 것은 객체에게 어떤 일을 수행하도록 요구하는 것  함수

 ** 예) 원 객체 : 상태-radius,행동-getArea()

 

→ 객체는 상태와 행동 모두를 가짐

→ 상태는 객체 자체를 정의하고, 행동은 객체가 무엇을 할 것인지를 정의하는 것이다.

 

 

ㅇ 클래스와 객체

- 클래스 : 객체의 데이터와 함수가 무엇이 될지를 결정하는 템플릿이며 설계도

- 객체 : 클래스의 인스턴스

 → 클래스의 여러 가지 인스턴스를 만듦 = 실체화

 

 

ㅇ 생성자

class Circle { // 클래스; 아직 객체 아님
public :
  double radius; // 데이터필드(속성)
 
 /* 생성자(오버로딩) */
 Circle() 
 { // 인수 없는 생성자
   radius = 1; 
 }

 Circle(double newRadius)
 { // 인수 있는 생성자
   radius = newRadius; 
 }

 /* 일반 함수 */
 double getArea()
 { 
    return radius * radius * 3.14159;
 }
};

- 특별한 유형의 함수

- 새로운 객체가 생성될 때 호출됨

- 일반적으로 객체의 데이터 필드에 초기 값을 주는 초기화 과정을 수행하기 위해 설계됨

- 클래스 이름과 같음

- 여러 개의 생성자 사용 가능; 오버로딩

  * 오버로딩을 통해 초기 데이터 값을 갖는 객체에 대해 쉽게 구성 가능

- 인수 없는 생성자 / 인수 있는 생성자

- 기본 생성자 : 인수 없는 생성자 + 비어 있는 바디 → 어떠한 생성자도 선언하지 않을 경우에만 자동적으로 주어짐

 

※ 일반함수와의 차이점

 1. 생성자는 클래스와 같은 이름을 가짐

 2. 생성자는 반환 값 유형을 가지지 않음 (void 주의)

 3. 생성자는 객체가 생성될 때 호출된다. 객체를 초기화하는 역할.

 

 

※ 생성자 초기화 목록

생성자에서 필드를 초기화하는 작업만을 할 때는 다음과 같이 나타낼 수 있음

ClassName(parameterList) : datafield1(value1), datafield(value2)
{
	// 생성자가 할 일
}

 

 

ㅇ 객체이름

- 객체 생성시 이름 할당할 가능

- 객체 생성시 생성자가 호출됨 (객체 생성 = 생성자 호출)

→ 따라서 객체 생성시 생성자를 이용할 수 있음

  * 인수 없는 생성자 → 클래스명 변수명()

  * 인수 있는 생성자 클래스명 변수명(인수);

 

- 객체 이름으로 접근 가능!

  * .을 이용하여 데이터 접근 및 함수 호출

int main() 
{
  // 다른 데이터 필드. 같은 함수 공유
  Circle circle1;			// 인수없는 생성자
  Circle circle2(5.0); 		// 인수있는 생성자

  // circle1의 radius와 getArea()값 출력
  cout << "Radius: " << circle1.radius <<" Area: " << circle1.getArea();
  
  // circle2의 radius를 100으로 변경하고
  circle2.radius=100;        
  
  // radius와 getArea 값 출력
  cout << "Radius: " << circle2.radius <<" Area: " << circle2.getArea();   
  
  return 0;
}

 

* 객체 복사 : circle1 = circle2 

  - 복사 후에도 여전히 두 개의 객체(함수는 계속해서 공유) 

* 익명객체 : 종종 객체를 생성하고 단지 한 번만 객체를 사용하는 경우(객체가 후에 참조되지 않을 때) 이름없이 사용

 - 클래스명(), 클래스명(인수) // circle1= Circle(5);

 

* 클래스 멤버로서 데이터 필드를 선언할 때는 초기화가 불가, 생성자에서만 초기화 가능! 

 

 

* 객체의 배열

- 일반 변수와 같음, 단지 객체단위일 뿐

  Circle circleArray[10];

  Circle circleArray[3] = {Circle(3), Circle(4), Circle(5)};  // 인수있는 생성자로 배열 초기화

 

 

 

ㅁ 헤더파일 분리 선언

- 같은 파일 안에서 main 함수와 함께 클래스를 선언하면 다른 프로그램에서는 이들 클래스를 사용할 수 없게 됨

- 클래스를 재사용하기 위해서 분리된 헤더파일 선언!

 

 

ㅇ 클래스 선언 (.h)

클래스 안에 어떤 데이터와 함수가 있는지를 컴파일러에게 알려주는 것

- 모든 데이터 필드, 생성자 원형, 함수 원형 선언

/* Circle.h 헤더 */

class Circle 
{
  public :
    // 멤버변수
    double radius;
    
    // 생성자
    Circle() ;
    Circle(double);

	// 멤버함수
    double getArea();
};

<circle.h>

 

ㅇ 클래스 구현(.cpp)

함수가 어떻게 동작하는 지를 컴파일러에게 알려주는 것

- 생성자와 함수도 구현

#include "Circle.h"		// 헤더포함

// 생성자;  멤버변수 초기화
Circle::Circle() {
  radius = 1;
}

Circle::Circle(double newRadius) {
	radius= newRadius;
}

double Circle::getArea() {
	// 멤버함수 구현
	return radius* radius * 3.14159;
};

<circle.cpp>

 

/* 메인함수 */
#include <iostream>
#include "Circle.h"
using namespace std;

int main() {
	Circle circle1;
	Circle circle2(5.0);

	...	
	
    return 0;
}

<TestCircleWithDeclaration.cpp (client)>

 

ㅇ 이항영역결정연산자

-  Triangle::getArea() :  Triangle 클래스에 정의되어있는 getArea()

 

 

ㅇ 포인터를 사용한 객체 멤버 접근

Circle circle1;

Circle *pCircle = &circle1;  인 경우

 - circle1.radius / (*pCircle).radius / pCircle -> radius와 같이 접근 가능

 

 

* 힙에서의 동적 객체 생성

  - 스택 안에서 생성된 객체는 함수가 반환될 때 스택에서 삭제됨

  - 함수가 반환될 때 객체를 남겨놓기 위해서는 힙에 동적으로 생성해야 함(new연산자 사용)

    ClassName *pObject = new ClassName();

    ClassName *pObject = new ClassName(인수);

 - 동적으로 할당한 객체를 확실하게 삭제하기 위해서는 delete연산자 

   delete pObejct;

 

 

 

ㅇ 데이터 캡슐화

- public은 직접 수정이 가능

 예) cricle1.radius=5;

 → 데이터가 함부로 수정될 수 있음

 → 클래스를 유지하기 어렵게 하고 버그도 발생하기 쉽게 만듦

 → 데이터필드 캡슐화 : 속성에 대한 직접적인 수정을 피하기 위해 private 접근지시자 사용!

 

* public : 모든 데이터 필드, 생성자, 함수가 클래스의 객체로부터 접근될 수 있다는 것을 나타냄(↔ private)

* private : 클래스 밖에서는 직접 참조를 통하여 접근할 수 없음

  - get함수(게터, 접근자) : 해당 변수를 호출하는 함수

  - set함수(세터, 변경자) : 변수를 직접 수정하는 변수

 

class Circle 
{
	public :
		Circle();
		Circle(double);
		
        double getArea();
		double getRadius();
		void setRadius();

	// private으로 선언하여 데이터 캡슐화
	private :
		double radius;
};

<circle.h>

#include "Circle.h"

Circle::Circle()
{
	radius = 1;
}

Circle::Circle(double newRadius)
{
	radius= newRadius;
}

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

double Circle::getRadius()
{
	return raidus;
}

void Circle::setRadius(double newRadius) 
{
	radius =(newRadius >=0) ? newRadius :0;
}

<circle.cpp>

#include <iostream>
#include "Circle.h"
using namespace std;


int main() 
{
	Circle circle1;
	Circle circle2(5.0);
    
	// radius가 private으로 선언되었으므로
	// set함수를 이용하여 radius를 100으로 변경해야함
	circle2.setRadius(100);   

 	// radius와 getArea 값 출력
	cout<< "Radius : " << circle2.getRadius << " Area: " << circle2.getArea();  

	return 0;
}

<TestCircleWithDeclaration.cpp (client)>

 

 

ㅇ this 포인터

숨겨진 데이터 필드를 호출 개체로 참조할 수 있도록 특별히 제작된 포인터

Circle::Circle(double radius) 
{
	// private인 radius 접근
	this->radius = radius; 
	(*this).radius = radius; 	// 동일 표현
}

 

 

 

ㅇ 객체를 함수로 전달하는 법

1) 값에 의한 전달

2) 참조에 의한 전달

3) 포인터를 통한 참조에 의한 전달

 

 

 

반응형
그리드형

댓글

❤️김세인트가 사랑으로 키웁니다❤️