Language/C++

07.OOP

아무키 2023. 12. 22. 17:00
반응형

절차적 프로그래밍 (Procedural Programing)

프로그램이 수행하는 일련의 작업을 기준으로하는 프로그래밍 패러다임

작업의 구현 = 함수 / 함수의 집합 = 프로그램

데이터와 작업이 분리되어 있는 개념

데이터는 작업의 실행을 위해 매개변수로 전달될 뿐

이해가 쉬운 방식

 

절차적 프로그래밍의 단점

함수 데이터의 구조를 정확히 알아야 함

→ 데이터가 변하면, 함수의 수정이 필요

Tightly coupled

 

프로그램의 규모가 커지면

→ 이해하기 어렵고

→ 유지 /보수하기 어렵고

→ 확장하기 어렵고

→ 디버깅하기 어렵고

코드를 재사용하기 어렵고

→ 오동작할 확률이 커진다.

 

객체지향 프로그래밍(Object Oriented Programming)

절차적 프로그래밍의 단점을 극복하기 위해 제안된 프로그래밍 패러다임 중의 하나

C++, C#, Java등에서는 이러한 방식을 손쉽게 구현할 수 있는 언어의 문법을 제공

→ 함수형 프로그래밍 등 새로운 패러다임을 적용할 수 있도록 언어는 계속 확장 될 수 있다.

클래스와 객체를 기반으로 함

데이터와 작업을 하나로 묶어서 표현

 

객체지향 프로그래밍의 특징

1 캡슐화

→ 객체는 (데이터) + (데이터를 기반으로 한 동작인 함수)을 구현

2 정보 은닉

→ 사용자는 내부 구현에 대해 알 필요도 없고, 알아서도 안됨

→ 잘못된 사용 및 수정을 방지

→ 사용자는 외부로 노출된 인터페이스만 활용 가능

→ 테스트, 디버깅, 유지보수, 확장이 용이해짐

3 상속

4 다형성

 

절차적 프로그래밍의 상위 호환이 아니다

잘 설계된 절차적 프로그램 > 잘못 설계된 객체지향 프로그램

모든 문제에 어울리는 설계 방안이 아님

모든 대상이 클래스로 치환되는 것은 아님

객체지향 프로그램은 어렵다, 특히 C++

문제를 분석하여 좋은 설계 사양서를 만들어야한다.(어렵다)

성능에서 손해를 보거나, 복잡한 코드가 작성되기도 함

 

Classes and Objects

 

클래스

객체(object)가 생성되기 위한 틀

→ 객체가 가져야 할 데이터와 기능을 정의

사용자 정의 “자료형” (user-defined data-type)

멤버 변수를 가짐(데이터)

→ 속성(property, attribute), 필드(field), 클래스 변수(class variable) → 멤버 변수의 또다른 용어

멤버 함수를 가짐(함수, 동작)

→ Method → 멤버 함수의 또다른 용어

데이터 함수를 은닉 가능

인터페이스를 공개 가능

 

객체

클래스로부터 생성된 객체

→ (메모리에 올라간 객체는 인스턴스로 구분하여 명명하는 경우도 있다)

객체는 개별적으로 관리되며, 원하는 만큼 생성 가능하다.

객체를 통해 클래스에 정의된 멤버 함수를 호출 가능

 

개념적인 예

→ ”철수”는 학생이라는 클래스의 객체

→ ”영희”도 학생이라는 클래스의 객체

→ 철수와 영희는 각각 학번, 키, 나이등의 멤버 변수(데이터)를 갖고 있다.

 

클래스와 객체

클래스는 자료형(ex : int) 처럼 사용함

클래스는 새로운 데이터 타입을 만드는 것

int highScore;
int lowScore;

Player Kim;
Player Lee;

 

클래스의 정의 (Class Definition)

 

기본 모양

class ClassName{
	//declarations;
};

 

예시

class Player{
	//attributes
	std:string name;
	int helth;
	int xp;    // <- 멤버 변수, 데이터들

	//method
	void Talk(std::string text);
	bool IsDead(); // <- 멤버 함수, 행위 /기능
};

 

객체의 생성

Player khk;
Player hero;

Player *enemy = new Player();
delete enemy;

 

계좌 클래스

class Account{
	std::string name;
	double balance;

	bool Withdraw(double amount); // 출금
	bool Deposit(double amount); // 입금
};

Account kimAccount;
Account leeAccount;

Account *parkAccount = new Account();
delete parkAccount;

 

클래스 멤버의 접근 (Accessing Class Members)

멤버 변수

멤버 함수

어떠한 멤버 변수 / 함수는 접근이 불가능 할 수있음(정보 은닉)

멤버 변수/ 함수에 접근하기 위해서는 객체가 필요

→ (Static 멤버의 경우는 예외)

 

클래스 객체인 경우

’.’ 연산자 사용 (멤버 접근 연산자)

Player player1;

player1.name;
player1.Move(2, 3);

 

객체의 포인터인 경우

역참조 후 점 연산자 사용

Account *kim_account = new Account();

(*kim_account).balance;
(*kim_account).Deposit(1000.00);

 

 

화살표 연산자(member of pointer 연산자) 사용

Account *kim_account = new Account();

kim_account -> balance;
kim_account -> Deposit(1000.00);

// (*ptr).balance 는 ptr -> balance 같다.

 

Class Member Access Modifier (visibility)

정보 은닉을 위해 멤버 접근을 제한할 수 있음

 

클래스 멤버 접근 제한자

public

→ 어디서든 접근 가능

private

클래스의 멤버, friend 클래스에서만 접근 가능

protected

→상속된 클래스의 객체에서만 접근 가능

class Player{
	public:
		void Talk(std::string text);
		bool IsDead();
	private:
		int health;
		int xp;
};

 

클래스 멤버 접근 제한자의 적용

private 멤버에 접근하기 위해서는 public 멤버 함수가 필요

 

전부 public으로 할 경우

→ 멤버에 직접 접근하는 것이 오류를 초래할 수 있다.

→ 게임 플레이어 체력 100이 아닌 1000 할당도 가능

Player kim;
kim.name = "KQW" //compiler error;
kim.health = 1000; //error;
kim.Talk("Ready"); // ok

Player *enemy = new Player();
enemy -> xp = 100; // error;
enemy -> Talk("Read"); //ok

delete enemy;

 

계좌 객체 예시

계좌 잔액(balance)에 문제가 있다면? 입금(deposit)만 살펴보면 된다.

→ 잔액에 직접 접근이 불가능하고, public 입금 멤버함수를 통해서만 접근이 가능하기 때문

테스트 및 디버깅이 쉬워진다.

Account kimAccount;
kim_account.balance = 1000.0; //compiler error
kim_account.Deposit(1000.00); //ok
kim_account.name = "Kim's Account"; //error

Account *leeAccount = new Account();
lee_account -> balance = 1000.00; //error
lee_account -> Withdraw(1000.00); //ok

delete leeAccount;

 

멤버 함수의 구현 (Implementing Member Methods)

 

기존 함수의 구현과 유사

멤버 변수에 접근이 가능하기 때문에 인자로 전달할 데이터가 적어짐

클래스 선언 내에 구현 가능

→ Inline 구현

클래스 선언 외부에서도 구현 가능

→ Class_name::method_name

명세(specification)와 구현의 분리

→ 클래스의 선언은 .h 파일에 작성

→ 클래스의 구현은 .cpp파일에 작성

 

클래스 선언 내에 구현

class Account{
public:
	void SetBalance(double bal){
		balance = bal;
	}
	double GetBalance(){
		return balance;
	}
private:
	double balance;
};

 

클래스 선언 외부에 구현

class Account{
	public:
		void SetBalance(double bal);
		double GetBalance();
	private:
		double balance();
};

void Account::SetBalance(double  bal){
	balance = bal;
}

double Account::GetBalance(){
	return balance;
}

 

명세와 구현의 분리

헤더 파일(.h)

→ include guard를 통해 전처리기에서 중복적인 헤더 파일의 선언을 방지

 

파일이름은 주로 클래스 이름과 동일

#infdef _ACCOUNT_H_
#define _ACCOUNT_H_

class Account
{
public:
	void SetBalance(double bal);
	double GetBalance();
private:
	double balance;
};

#endif // <- include guard

 

구조체와 클래스 Struct vs Class

 

c++에서는 구조체와 클래스 모두 사용 가능

문법적으로는, 기본 접근 권한의 차이 외에는 차이점이 존재하지 않음

→ 클래스 : 명시되어 있지 않으면 private가 기본값

→ 구조체 : 명시되어 있지 않으면 public이 기본값

class Person{
	std::string name;
	std::string GetName();
};

Person p;
p.name = "Kim"; //error
cout << p.GetName(); // error

struct Person{
	std::string name;
	std::string GetName();
};

Person p;
p.name = "Kim"; // ok;
cout << p.GetName(); // ok

 

구조체와 클래스 사용 가이드라인

구조체

→ Public 접근이 필요한 데이터로 사용

→ 멤버 함수를 구조체 안에 설정하지 않는 것을 권고

 

클래스

→ Private 멤버 변수와 멤버 함수

→ 멤버 함수를 통해서 멤버 변수에 접근하도록 get/set 구현

반응형