본문 바로가기
c, c++/c++로 시작하는 객체지향 프로그래밍

9.1~9.5) 클래스와 객체 생성

by 피스타0204 2024. 1. 21.

9.1)

c++은 객체지향 프로그래밍(object-oriented programming, OOP)를 제공하는 언어입니다.

c++에서 객체 (혹은 인스턴스)는 클래스(class)에 의해 정의되는 데

클래스는 크게 변수를 저장하는 데이터 필드와 함수로 이루어집니다.

객체의 데이터 필드와 함수는 클래스가 아닌 각각의 객체에 종속적이기 때문에 인스턴스 멤버 변수(instance member variable), 인스턴스 멤버 함수(instance member function)이라고도 합니다.

 

9.2) 

클래스는 붕어빵 틀, 클래스에 의해 만들어지는 객체는 붕어빵으로 비유되고는 합니다.

클래스는 객체를 초기화 시켜주는 생성자(constructor) 함수를 제공합니다. 생성자 함수와 클래스의 이름은 항상 같아야 하기 때문에 동일하게 취급되고는 합니다.

 

9.3)

아래의 예제에서는 원의 넓이를 구하는 클래스와 함수를 보여주고 있습니다.

여기서 객체의 상태(state) 혹은 속성(property)는 데이터필드인 radius를 나타내고 있고, 객체의 행동(behavior) 혹은 동작(action)은 함수 getArea()가 수행하고 있습니다.

 

예제1>

#include <iostream>
using namespace std;

class Circle
{
public:
	double radius; //데이터 필드

	Circle() //생성자 함수
	{
		radius = 1;
	}
	Circle(double newRadius) //생성자 함수의 이름은 클래스와 같아야 하는가?
	{
		radius = newRadius;
	}

	double getArea() {
		return radius * radius * 3.141592;
	}
};

int main() {
	Circle circle1(1.0);//생성된 객체이름 :circle1
	Circle circle2(25); //반올림되는 이유를 모르겠음
	Circle circle3(125);

	cout << "The area of the circle of radius" << circle1.radius 
		<< "is" << circle1.getArea() << endl;
	cout << "The area of the circle of radius" << circle2.radius 
		<< "is" << circle2.getArea() << endl;
	cout << "The area of the circle of radius" << circle3.radius 
		<< "is" << circle3.getArea() << endl;

	circle2.radius = 100;

	cout << "The area of the circle of radius" << circle2.radius 
		<< "is" << circle2.getArea() << endl;
}

 

출력값

 

 

예제2>

다음 UML 표기법(UML클래스 다이어그램)을 보고 채널과 볼륨을 올리고 내릴 수 있는 TV리모컨 프로그램을 작성하시오.

#include <iostream>
using namespace std;

class TV
{
public:
	int channel;
	int volumeLevel;
	bool on;
	
	TV() //초기값을 부여하는 생성자 함수
	{
		channel = 1;
		volumeLevel = 1;
		on = false;
	}
	void turnOn() {
		on = true;
	}
	void turnOff() {
		on = false;
	}
	void setChannel(int newChannel) {
		if (on && (newChannel <= 120) && (newChannel >= 1)) {
			channel = newChannel;
		}
	}
	void setVolume(int newVolumeLevel) {
		if (on && (newVolumeLevel >= 1) && (newVolumeLevel <= 7)) {
			volumeLevel = newVolumeLevel;
		}
	}
	void channelUp() {
		if (on &&(channel < 120)) {
			channel++;
		}
	}
	void channelDown() {
		if (on && (channel > 1)) {
			channel--;
		}
	}
	void  volumeUp() {
		if (on && (volumeLevel < 7)) {
			volumeLevel++;
		}
	}
	void volumeDown() {
		if (on && (volumeLevel > 1)) {
			volumeLevel--;
		}
	}
};

int main() {
	TV tv1;
	tv1.turnOn();
	tv1.setChannel(30);
	tv1.setVolume(3);

	TV tv2;
	tv2.turnOn();
	tv2.channelUp();
	tv2.channelUp();
	tv2.volumeUp();

	cout << "tv1's channel is" << tv1.channel
		<< "  and volume level is" << tv1.volumeLevel << endl;
	cout << "tv2's channel is" << tv2.channel
		<< "  and volume level is" << tv2.volumeLevel << endl;
}

 

출력값

9.4) 생성자

생성자는 함수의 특별한 유형이며 세가지 특성이 있습니다.

첫째, 생성자는 클래스 자신과 같은 이름을 가진다.

둘째, 생성자는 반환유형(void 반환도 불가)이 없다.  void circle(){} 형태로 호출해야 한다.

셋째, 생성자는 객체가 생성될 때 호출된다. 생성자는 객체를 초기화 한다. 생성자를 통해 변수에 초기값을 넣는다.

 

생성자 또한 함수이기 때문에  c++에서 제공하는 함수 오버로딩(같은 이름으로 다른 변수를 받는 것)이 가능합니다.

또, 클래스는 일반적으로 인수가 없는 생성자(no-argument constructor)을 제공합니다.

또한, 클래스는 생성자 없이 정의될 수 있습니다. 이때는 기본 생성자(default constructor)가 자동으로 제공됩니다.

 

아래의 사진 처럼 초기화 목록(initializer list)을 사용하여 생성자 내에서 데이터 필드를 초기화 할 수 있습니다.

default constructor를 포함하여 no-argument constructor가 하나도 없을 경우, 즉 모든 생성자가 인자를 가지고 있을 경우에ㄴ 반드시 초기화 목록을 사용해 생성자를 초기화해야 합니다.

오른쪽이 초기화 목록(initializer list)을 사용한 코드

 

9.5) 객체의 생성과 호출

클래스를 만들었다면 다음은 객체를 생성하고 객체 안에 저장된 데이터 필드와 함수를 호출해야 합니다. 

일반적으로 객체를 생성할 때는 아래와 같이 ()가 들어 가지 않지만 그 객체를 한번만 쓰고 다시 쓰지 않을 생각이라면 익명 객체(anonymous object)를 선언할 수도 있다. 단, 익명객체는 반드시 (괄호)를 포함해야 합니다.

className objectName; //객체 생성 코드

objectName.functionName(); //함수 호출

objectName.Datafield; //변수호출

익명 객체(anonymous object)

만든 객체는 다른 객체에 데이터 필드를 복사할 수 있습니다. 또, 아래와 같은 방식으로 익명 객체의 데이터필드를 복사할 수 있습니다.

Circle c1(5);
Circle c2(6);

c1 =c2;  //c2의 변수 c1으로 복사
c2 = Circle(7); //익명 개체 복사

 

---

check point!

9.1) 객체와 객체의 클래스의 정의와 관계를 설명하라. 클래스 정의는 어떻게 하는가? 객체를 선언하고 생성하는 방법은 무엇인가?

: 클래스는 붕어빵틀, 객체는 붕어빵으로 비유할 수 있습니다. 클래스에서 미리 형식을 정해놓고 객체가 필요할 때마다 생성하여 사용합니다. (책에서의 정의) 클래스는 객체의 데이터 필드와 함수가 무엇이 될지를 결정하는 템플릿, 설계도라고 볼 수 있으며 객체는 클래스의 인스턴스입니다. 

 class CLASSNAME
 {
 public:
 	int DATAfI;
    bool DATAFIELD;
    CLASSNAME()
    {
    	DATAFI = 1; //초기값
    	DATAFILED = FALSE; //초기값
    }
    void FUNCTION(int NEWdata) //객체 생성 후 입력
    { //동작}
 }
 
 int main()
 {
 	CLASSNAME OBJECTNAME;
    OBJECTNAME.FUNCTION(30);
 }

9.2) 생성자와 함수의 차이점은 무엇인가?

: 생성자는 객체를 초기화하는 클래스만의 특별한 함수입니다.

 

9.3) 인수 없는 생성자를 사용하여 객체를 생성하는 방법은 무엇인가? 인수있는 생성자를 사용하여 객체를 생성하는 방법은 무엇인가?

: 인수 없는 것은 일반적으로 많이 사용하는 방법으로 객체를 생성할 수 있고 인수 있는 생성자를 사용하는 경우, 경우에 따라 초기화 목록을 사용해야 합니다.

 

9.4) 객체 이름이 선언된 수, 다른 객체를 참조하기 위해 객체 이름을 재할당할 수 있는 가?

: 선언된 객체이름은 배열이름처럼 다시 할당할 수 없습니다. 따라서 한번 사용하는 객체의 경우 익명객체(annonymous object)를 사용하는 것이 좋습니다.

 

9.5) 리스트 9.1에서 정의된 Circle 클래스를 사용하였을 때 다음 코드의 출력은 무엇인가?

Circle c1(5);

Circle c2(6);

c1 = c2;

cout << c1.radius << " " << c2.radius << endl;

: 6 6

 

9.6) 다음 코드는 무엇이 잘못되었는가? (리스트 9.1 TestCircle.cpp에 정의된 Circle 클래스를 사용한다.)

(a)

int main()

{

Circle c1();

count << c1.getRadius() << endl;

return 0;

}

: getRadius라는 이름의 함수가 없음.

 

(b)

int main()

{

Circle c1(5);

Circle c1(6);

return 0;

}

: 객체는 여러번 초기화할 수 없음.

 

9.7) 다음 코드는 무엇이 잘못되었는가?

class Circle

{

public:

    Circle()

{

}

double radius = 1;

}

: 생성자를 제대로 작성하지 않아서 데이터필드가 초기화되지 않았다.

 

9.8) 다음 문장 중 올바른 문장은 어느 것인가?

Circle c;

Circle c();

전자가 일반적으로 맞는 말이다. c라는 객체를 생성하여 계속 사용하고 싶다면 Circle c; , 임시 객체를 생성하고 싶다면 Circle c(); 하여 사용한다.

 

9.9) 다음 두 문장을 서로 독립적인 것으로 가정하는 경우, 올바른 문장인가?

Circle c;

Circle c = Circle();

: 예, 임시 객체를 사용할 수 있음.

 

 

 

'c, c++ > c++로 시작하는 객체지향 프로그래밍' 카테고리의 다른 글

11.1~11.5  (1) 2024.04.04
10.3~10.10  (2) 2024.03.28
9.8~9.10)클래스에서 함수와 변수  (0) 2024.02.02
9.6~9.7) 헤더파일 분리  (1) 2024.01.28
확인할 수 없는 외부 참조 오류  (0) 2024.01.27