전방 선언

-> 외부 파일 어딘가에 해당 클래스가 존재한다고 알려주는 역할

 

다양한 파일들을 만들고 서로 엮는 과정에서 불필요한 파일의 정보까지 가져오는 상황이 발생한다.

이를 해결하기 위해서 전방 선언을 사용하는 것이 좋다.

 

include와 전방 선언의 차이점

 

include

-> 기존에 존재하는 정보를 확인할 수 있다.

 

전방 선언

-> 어딘가에 존재한다는 것을 알 수 있지만 상세한 정보는 알 수 없다.

 

전방 선언의 장점

#1. 파일의 크기가 작아진다.(컴파일 속도의 향상)

 

전방 선언 시 주의 사항

 

#1. 존재만 알려준다.

-> 프로그램에서 전방 선언한 것이 존재하는지 검사를 하지 않는다.

-> 오타가 발생할 경우 찾기 힘들다.

 

#2. 존재만 알기 때문에 객체를 만들 수 없다.

-> 단, 포인터형으로는 사용이 가능하다

 

#3. 객체의 멤버 함수를 사용하는 곳은 .cpp파일이다.

-> .cpp파일에서는 include를 해주어야 한다.

 

사용 예)

A.h      // A 헤더 파일

class B; // 전방 선언
class C; 

class A
{
private:
    B* m_B; // 전방 선언시에는 포인터 변수로만 선언이 가능하다.
    C* m_C;
}

B.h      // B 헤더 파일
class B
{
  코드 블럭;
}

C.h      // C 헤더 파일
class C
{
  코드 블럭;
}

A.cpp     // 소스 파일

#include "B.h" // .cpp 파일에는 전방 선언한 것을 인클루드
#inlcude "C.h" 
class CObj
{
public:
	//생성자의 형태
	CObj()
	{
	    cout << "생성자 호출" << endl;
	}
	CObj(int _a, double _b)
	{
		m_iA = _a;
		m_dB = _b;
		cout << "인자 있는 생성자 호출" << endl;
	}

private:
	int		m_iA;
	double	m_dB;
};

 

생성자

-> 객체 생성 시 자동으로 호출 되는 것.

-> 사용자가 호출하지 않는다.

-> 함수의 일종으로 인자 타입, 인자 개수에 따른 오버로딩이 가능하다.

-> 클래스의 이름으로 정의된다.

-> 반환 타입이 없다.

-> 객체 생성은 외부에서 진행하기 때문에 생성자의 멤버 접근 지정자는 public으로 설정한다.

-> 객체는 생성자에 의해 완성된다.

 

생성자의 주 사용 목적

-> 객체 멤버로 초기화할 값이 있을 경우 사용한다.

 

생성자로 데이터를 전달하는 방법

-> C++ 초기화 형식과 동일하다.

CObj obj(10, 3.14);

 

생성자 사용 시 주의 사항

 

#1. 객체 생성은 생성자 호출에 의해 완성된다.

-> 호출할 생성자가 없을 경우 객체를 만들 수 없다.

-> 오버로딩을 이용하여 생성자를 여러 개 정의해주어야 한다.

CObj	obj1;
CObj	obj2(10, 3.14);

#2. 디폴트 생성자

-> 사용자가 생성자를 정의하지 않을 경우 컴파일러는 디폴트 생성자를 자동으로 생성하여 호출한다.

-> 단, 사용자가 한개 이상의 생성자를 정의할 경우 디폴트 생성자는 생성하지 않는다.

 

explicit 키워드

-> 생성자 앞에  explicit 키워드를 명시하면 C기반의 초기화(형 변환)을 막는다.

class CObj
{
public:
	explicit CObj() {}
	explicit CObj(int _a) { m_a = _a; }

public:
	void Func()
	{
		cout << m_a << endl;
	}

private:
	int		m_a;
};
// C기반의 초기화
CObj	obj2 = 10; // 불가능

-> 초기화는 무조건 C++기반의 초기화만 허용한다.

// C++기반의 초기화
CObj	obj2(10); // 가능

예를 들어 다음과 같이 대입을 하게 되면

CObj	obj3 = 20;

대입 연산자 기준 좌측은 사용자 정의 자료형, 우측은 int형이다.

즉, 타입이 다른 자료형끼리 대입이 진행되고 있다.(초기화가 가능)

 

대입 연산자 기준 좌측 자료형으로 형 변환이 발생했다.

20이라는 int형 데이터가 CObj Temp(20) 이라는 형태로 형 변환이 발생하고,

CObj obj3 = Temp 형식으로 값을 대입하고 있다.

 

형 변환이 발생한다 하여도 사용자가 보기에는 어색함이 있을 수도 있다.

이를 방지하기 위하여 explicit 키워드를 사용한다.

 

소멸자

-> 객체 소멸 시 자동으로 호출되는 것.

-> 생성자와 비슷하지만 반대 개념이다.

-> 사용자가 소멸자를 정의하지 않을 경우 컴파일러가 디폴트 소멸자를 자동으로 생성하여 호출한다.

-> 사용자가 소멸자를 정의하면 디폴트 소멸자는 생성되지 않는다.

-> 객체 소멸 또한 외부에서 진행되기 때문에 public으로 설정해준다.

-> 객체 멤버로 동적할당한 변수가 있을 경우 해제하는 용도로 사용한다.

class CObj
{
public:
	CObj() { cout << "생성자 호출" << endl; }
	~CObj() { cout << "소멸자 호출" << endl; }

};

 

생성자와 소멸자의 호출 순서

객체 생성 -> 메모리 할당 -> 생성자 호출 -> 소멸자 호출 -> 메모리 해제 -> 객체 소멸

'Programming > C++ Basic' 카테고리의 다른 글

C++ 파일 입출력(fopen_s, fread(), fwrite())  (0) 2020.09.13
C++ 전방 선언  (0) 2020.09.13
C++ 메모리 함수  (0) 2020.09.13
C++ 클래스, 클래스의 4대 속성  (1) 2020.09.10
C++ Debug, 조건식 Debug  (0) 2020.09.08

메모리 함수

-> 메모리 vs 메모리 단위로 복사, 초기화를 수행하는 함수.

-> 메모리에 직접 접근하여 데이터를 다루기 때문에 속도가 빠르다.

 

#1. memset

-> 초기화 함수

-> 1byte 단위로 초기화를 진행한다.

-> 연속된 메모리를 사용하는 공간을 초기화할 때 사용한다.

void* _Dst : 초기화할 메모리의 시작 주소 전달

int _Val : 초기화할 값

size_t _size : 시작 주소부터 얼마만큼 크기를 초기화할 것인지 전달(byte단위)

int a;

     a = 0;

	memset(&a, 1, sizeof(int));		// 16843009
	// 0000 0001   0000 0001   0000 0001   0000 0001

 

memset(ptr, 0, sizeof(int) * 5);

int* ptr = new int[5];

for(int i = 0; i < 5; ++i)
{
 ptr[i] = 0;
}

여기서 memset과 for문은 서로 같다.

 

#2. memcpy

-> 메모리 복사 함수

void* _Dst : 복사 받을 메모리의 시작 주소

const void* _Src : 복사 할 메모리의 시작 주소

size_t _size : 얼마만큼 복사할 것인지 크기(byte단위)

 

int a = 0, b = 10;
	
memcpy(&a, &b, sizeof(int));
a = b;

여기서 memcpy는 a를 b에 대입한 것과 같다.

 

#3. memmove

-> 메모리 복사 함수

-> memcpy와 수행은 똑같다.

 

memcpy와 memmove의 차이점

memcpy memmove
표준이 아니다.
복사할 곳에 직접적으로 복사가 진행된다.
표준이다.
임시 버퍼를 통해 복사를 진행한다.

메모리가 겹칠 경우에는 memcpy 함수보다는 memmove를 사용해야한다.

'Programming > C++ Basic' 카테고리의 다른 글

C++ 전방 선언  (0) 2020.09.13
C++ 생성자와 소멸자, explicit 키워드  (2) 2020.09.13
C++ 클래스, 클래스의 4대 속성  (1) 2020.09.10
C++ Debug, 조건식 Debug  (0) 2020.09.08
C++ string  (0) 2020.09.08

절차 지향 프로그래밍

-> 동사구인 '~하다'에 중점을 둔 프로그래밍

-> 함수들이 각기 자신들의 기능을 절차에 의해 호출한다.

 

객체 지향 프로그래밍(OOP)

-> 객체에 중점을 둔 프로그래밍

 

 

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

-> 상속을 통한 재 사용성을 보장한다.

-> 유지보수 및 관리가 용이하다.

 

 

Message Passing

-> 프로그래밍을 구성하는 객체간의 의사소통이다.

-> 의사 소통은 각 객체들이 가지고 있는 함수를 통해 이루어진다.

예)

#1 함수를 통해서 플레이어의 공격력을 얻어온다.. 

#2 함수를 통해서 몬스터한테 얻어온 공격력만큼 전달하여 체력을 감소시킨다.

 

클래스란?

-> C++부터 등장한 사용자 정의 자료형

-> 변수와 데이터를 다루는 기능을 하나로 묶어 놓은 것이다.

-> 객체들을 추상화시킨 하나의 틀이다.

 

프로그래밍에서 객체란?

-> 클래스는 사용자 정의 자료형

-> 클래스에 변수명을 부여해서 메모리에 등록시키면 객체가 된다.

-> 메모리에 등록된 클래스는 Instance라고도 부른다.

 

추상화란?

-> 공통된 요소들을 추출하는 작업

class CCar
{
public:
	// 멤버 함수
	void Move()
	{
		cout << m_szName << "이(가) " << m_iSpeed << "속도로 움직입니다." << endl;
	}

public:
	// 멤버 변수
	// m_ : 멤버를 뜻하는 헝가리안 표기법
	char	m_szName[16];
	int		m_iSpeed;
};

struct tagCar
{
private:
	// C++부터 구조체도 멤버함수를 지닐 수 있다!
	void Move()
	{
		cout << m_szName << "이(가) " << m_iSpeed << "속도로 움직입니다." << endl;
	}

	char	m_szName[16];
	int		m_iSpeed;
};

 

멤버 접근 지정자

-> 멤버에 접근할 수 있는 권한을 뜻한다.

 

#1. private

-> 멤버 접근을 오로지 내부에서만 허용한다.

 

#2. public

-> 멤버 접근을 내/외부 모두 허용한다.

 

#3. protected

-> 멤버 접근을 내부 혹은 상속 관계에서만 허용한다.

 

클래스와 구조체의 차이점

#1. 멤버 접근 지정자의 차이점

클래스 : private

구조체 : public

 

그 외의 모든 기능들이 동일하다.

-> 즉, 멤버 접근 지정자 외에는 차이점은 없다.

 

클래스와 구조체의 차이점이 없는 상황에서 구조체 멤버로 함수를 정의하지 않는다.

-> 구조체는 순전히 데이터 덩어리 용도로만 사용한다.

 

클래스의 4대 속성

-> 클래스를 구성하는 속성들

 

#1. 은닉화

-> 멤버 변수를 숨긴다는 의미

-> 기본 멤버 접근 지정자를 private으로 두면서 외부로부터 원치않는 데이터 변경을 막는다.

-> 데이터 보호

 

은닉화를 도모하지 않을 경우 원치 않는 데이터로 변경될 가능성이 있다.

 

은닉화된 데이터를 다루는 방법

-> Get/Set 함수를 사용.

 

Get함수 : 데이터를 읽는 용도

Set함수 : 데이터를 쓰는 용도

 

 

#2. 캡슐화

-> 데이터와 데이터를 다루는 기능을 하나로 묶어 놓는다.

-> 내부가 어떻게 구성되었는지 보다는 기능이 중요하다.

 

예를 들어 정해진 순서의 세 가지의 함수를 순서대로 실행시키는 경우가 발생 하였을 때.

class A
{
pulic:
    void Take()
    {
     코드라인
    }
};

class B
{
pulic:
    void Take()
    {
     코드라인
    }
};

class C
{
pulic:
    void Take()
    {
     코드라인
    }
};

void main()
{
   A();
   B();
   C(); 
}

순서가 A -> B -> C가 아니고 B -> A -> C 이런식으로 섞이는 경우가 생길 수가 있다.

캡슐화로 이런 경우가 발생하는 것을 막을 수 있다.

class D
{
public:
	void Take()
	{
		A.Take();
		B.Take();
		C.Take();
	}
    


void main()
{
  D.Take();  
}

 

#3. 상속성

-> 클래스끼리 공통된 데이터를 필요로 한다면 상속을 통해 불러올 수 있다.

-> 부모 클래스는 자식 클래스들의 공통된 요소를 추출한 추상적인 존재가 된다.

 

 

#4. 다형성

-> 각기 다른 객체가 동일한 메세지를 통해 각기 다른 기능을 수행한다.

-> 상속과 맞물려 있기 때문에 상속을 어느정도 자유자재로 다룰 수 있으면 다형성은 쉽게 사용할 수 있다.

 

 

클래스의 파일분할
-> cpp에 정의부를 구현할 경우 어떤 클래스의 멤버 함수인지를 명시해주어야 한다.

'Programming > C++ Basic' 카테고리의 다른 글

C++ 생성자와 소멸자, explicit 키워드  (2) 2020.09.13
C++ 메모리 함수  (0) 2020.09.13
C++ Debug, 조건식 Debug  (0) 2020.09.08
C++ string  (0) 2020.09.08
C++ 레퍼런스 자료형  (0) 2020.09.08

+ Recent posts