[C++] OOP

솜몀·2024년 9월 4일
0

Keyboard

목록 보기
3/3

0.


1. 어셈블리 코드 확인 하는 방법
	[Compiler Explorer] godgolt.org
	x63 msvc v19.latest : MS Visual Studio Compiler

2. namespace 개념
	하나의 프로젝트를 여러명의 개발자가 같이 개발할 때, 동일한 요소이름을 사용할 수 있도록 하는 영역
	namespcae 문법을 사용하면 관련된 코드를 묶어서 관리할 수 있다. (함수, 구조체, 전역 변수)
	2.1 namespace 요소에 접근하는 방법
	- qualified name (완전한 이름) *권장됨
		Myspace::myFunc(); //사용
	-using declaration (선언)
		: namespace:: 이름 없이 '특정' 요소 사용가능
		using Myspace::myFunc(); //선언, main() 내부, 전역 공간 모두 선언가능
		myFunc(); //사용
	-using directive (지시어)
		: namcspace:: 이름 없이 namespace 안의 '모든' 요소를 사용가능
		using namespace Myspace; //선언
		myFunc(); //사용

	2.2. global namespace
		: 특정 namespace 에 포함되지 않은 공간, 아래 복잡한 경우의 수는 qulified name (완전한 이름) 을 사용하면 문제 발생하지 않는다.
		void myFunc() { } //선언, main부 밖 전역 공간.
		::myFunc(); //사용, global namespace 검색, 없으면 에러
		myFunc(); //사용, 열려있는 namespace 검색, 없으면 global namespace 검색

	2.3. std namespace
		: C++ 의 표준함수는 "std" namespace 안에 있다.
		: C++ 표준내부에는 수많은 요소들이 있으므로, 충돌방지를 위해 사용을 지양한다. '완전한 이름'을 사용할 것.
		using namespace std; //선언
		int n1 = max(10, 20); // 사용

	2.4. 중첩 (nested) namespace
		 : namespace 는 중첩(nested) 될 수 있다.
		 namespace Myspace
		 {
			namespace Myroom
			{}
		 }

	2.5. namespace alias
		: namespace 변수화
		namespace Myns = std::filesystem; //선언
		Myns::copyfile(); //사용

3. 헤더 파일
	: C++ 표준 헤더파일 이름에는 .h 가 붙어있지 않다. ex) #include <algorithm>
	: 사용자가 만든 헤더는 .h 을 붙인다.
	: C 스타일의 헤더는 C++ 버전이 별도로 존재한다. .h 를 떼고 앞에 c를 붙인다. ex) <stdio.h> -> <cstdio>
	: C++ 표준 헤더의 모든 요소는 std namespace 안에 모두 제공된다.
	: 일부 라이브러리들은 중첩되어 있다. ex) std::filesystem (파일관련), std::chrono (날짜/시간)

	3.1. namespace 와 파일 분할
		: 여러파일에 동일 namespace 사용가능
		: 헤더파일에 선언, 구현은 소스(.cpp) 파일에 한다.
		// [main.cpp]
		#include "Video1.h"
		#include "Video2.h"

		int main()
		{
			Video::init();
			Video::start();
		}
		
		// [Video1.h]
		namespace Video
		{
			void init();
		}

		// [Video1.cpp]
		namespace Video
		{
			void init()
			{
			}
		}

		// [Video2.h]
		namespace Video
		{
			void start();
		}

		// [Video2.cpp]
		namespace Video
		{
			void start()
			{
			}
		}

4. auto, decltype
	- auto
		: 변수 선언시, 우변의 표현식을 조사해서 컴파일러가 변수의 타입을 결정
	- deltype 
		: () 안의 표현식으로 타입을 결정

		int x[5] = {1,2,3,4,5};
		auto n = x[0]; // int n = x[0]
		decltype(n) n1; // int n1

		auto arr = x; // int* arr = x;
		decltype(x) arr1; // error

5. typedef, using
	- typedef
		: type 에 대한 별칭
	- using
		: type 에 대한 별칭 + template 에 대한 별칭

		typedef int MYTYPE;
		using MYTYPE = int;

		MYTYPE n;

6. 일관된 초기화 (Uniform Initialization)
	: C++11 이후 모든 종류의 변수를 동일한 방법으로 초기화 할 수 있도록 함.
	: 중괄호 초기화 (brace-init) 이라고도 부름

	-복사 초기화 (Copy Init.)
		: = 사용 초기화
		int n = {3};

	-직접 초기화 (Direct Init.)
		: = 없이 초기화
		int n{3};
	
	6.1. prevent narrow
	: 일관된 초기화시 타입보다 초기화 데이터가 클경우, 데이터 손실시 error 
	: 안정화 가능
	int n1 = 3.4 // ok
	
	int n2 = {3.4} // error
	int n3{3.4} // error

7. struct 와 structure binding

	struct Point
	{
		int x = 1;
		int y{2};
	}

	Point foo()
	{
		 Point p = {1,2}; //배열 
		 return p;
	}

	int main()
	{
		struct Point pt1; // C방식 구조체 선언
		Point pt1 = {3,4};

		// Structure Binding : 구조체 변수 가져오기 C++17
		auto [a,b] = pt1;
		//int a = pt1.x;
		//int b = pt1.y;

		int arr[3] = {1,2,3};
		auto [a,b,c] = arr;
		//int a = arr[0]; int b = arr[1]; int c = arr[2];

	}

8. 문자열
	: 문자열 처리 - char 배열을 사용해야 한다. =,== 연산자 사용불가
	: <string> 을 사용하면 변수처럼 +,==,= 등의 연산자 사용가능하다.
	: 주의 <cstring> 은 C<string.h> 의 C++ 버전, <string> 은 std::string 을 사용하기 위한 헤더
	#include <cstring>
	#include <string>
	
	char s1[] = "abcd";
	char s2[5];
	strcpy_s(s2,s1);

	std::string s1 = "wxyz";
	std::string s2;
	s2 = s1;

9. 디폴트 파라미터
	: 함수 호출시 인자 미전달시 "미리 지정된 인자 값"을 사용한다.
	void myFunc(int a, int b = 0, int c = 0)
	{
		a = b + c;
	}

	int main()
	{
		myFunc(1,2,3);
		myFunc(1,2);	//myFunc(1,2,0)
		myFunc(1);		//myFunc(1,0,0)
	}

	: * 마지막 인자 부터 차례대로 디폴트 값을 지정해야 한다.
	void myFunc(int a = 0, int b = 0, int c = 0); // ok
	void myFunc(int a    , int b = 0, int c = 0); // ok
	void myFunc(int a = 0, int b    , int c = 0); // error
	void myFunc(int a = 0, int b = 0, int c    ); // error
	
	: * 함수 선언/구현부로 분리 할 때는 "함수 선언부"에만 디폴트 인자를 표기해야 한다.
	void myFunc(int a = 0, int b = 0, int c = 0){} // error
	void myFunc(int a /*= 0*/, int b /*= 0*/, int c /*= 0*/){} // ok

10. Fuction Overloading
	: 함수 이름이 같아도, 인자 개수,타입이 다르면 "동일한 이름의 함수를 여러개 만들 수 있다."

	int sqr(int a)
	{
		return a * a;
	}

	double sqr(double a)
	{
		return a * a;
	}

	int main()
	{
		auto ret1 = sqr(3);
		auto ret2 = sqr(3.14);
	}
	
	: * 인자 모호함은 에러 발생 (리턴차입차이, 디폴트인자, 타입구분안되는 경우)
	void f1(int a) {return 1;}
	void f1(int a) {return 0;} //error
				   
	void f2(int a) {}
	void f2(int a, int b = 0) {}
	f2(1); // ambiguos error

	void f3(char  a) {}
	void f3(short a) {}
	f3('1'); // error - int => char/short 가능

	: 원리 - 컴파일러가 인수를 보고, 함수의 이름을 변경한다. name mangling (규칙은 컴파일러마다 다르다.)
	int sqr(int a)		-> sqr_i
	int sqr(double a)	-> sqr_d

1.

/*
* 문제점
1. int type 변수 4개를 사용하여 코드가 복잡해진다.
	: 사각형 타입이 없으므로, 사각형 한 개를 int 변수 4개로 표현하기 때문임
	-> struct : 사각형 타입을 만든다. [struct Rect]
* 
*/

#include <iostream>

int getRectArea(int x1, int y1, int x2, int y2)
{
	return (x2 - x1) * (y2 - y1);
}

void drawRect(int x1, int y1, int x2, int y2)
{
	std::cout << "DRAW RECT." << std::endl;
}

int main()
{
	int n = getRectArea(1, 1, 10, 10);
	drawRect(1, 1, 10, 10);
}

2.


/*
* 해결점
1. int type 변수 4개를 사용하여 코드가 복잡해진다.
	-> 사각형 타입이 없으므로, 사각형 한 개를 int 변수 4개로 표현하기 때문임
	-> 사각형 타입을 만든다. : 구조체 struct

* 문제점
1. struct 에  Call by Value 로 인수를 전달하여 "복사본 오버헤드"가 생긴다.
	: 인자로 전달된 변수를 수정하지 않겠다는 약속이 있다.
	: 그런데, 구조체 타입을 함수에서 인자로 전달될 때 Rect type data 크기만큼의 "복사본 오버헤드가 생긴다."
	-> Ref. : 함수에서 복사하지 않고 참조로 인자를 받아 사용한다. [Rect& r]
	-> const Refr. : 참조로 받을때 함수내에서 수정되지 않도록 한다. [const Rect& r]
	* 사용자 정의 타입을 인자로 전달할 때는 call by value 가 아닌, ref. 로 전달한다. 값 변경하지 않을 것이면 const ref. 로 전달.
*/

#include <iostream>

struct Rect // 필요한 사용자 정의 타입 설계
{
	int left;	// x1
	int top;	// y1
	int right;	// x2
	int bottom;	// y2
};

int getRectArea(Rect r)
{
	return (r.right - r.left) * (r.bottom - r.top);
}

void drawRect(Rect r)
{
	std::cout << "DRAW RECT." << std::endl;
}

int main()
{
	Rect rc = { 1, 1, 10, 10 };
	int n = getRectArea(rc);
	drawRect(rc);
}

3.

/*
* 해결점
1. int type 변수 4개를 사용하여 코드가 복잡해진다.
	-> 사각형 타입이 없으므로, 사각형 한 개를 int 변수 4개로 표현하기 때문임
	-> 사각형 타입을 만든다. : 구조체 struct

2. struct 에  Call by Value 로 인수를 전달하여 "복사본 오버헤드"가 생긴다.
	-> 인자로 전달된 변수를 수정하지 않겠다는 약속이 있다.
	-> 그런데, 구조체 타입을 함수에서 인자로 전달될 때 Rect type data 크기만큼의 "복사본 오버헤드가 생긴다."
	-> 함수에서 복사하지 않고 참조로 인자를 받아 사용한다. : Reference - Rect& r
	-> 참조로 받을때 함수내에서 수정되지 않도록 : Const Refr. 로 받는다 - const Rect& r
	-> * 사용자 정의 타입을 인자로 전달할 때는 call by value 가 아닌, ref. 로 전달한다. 값 변경하지 않을 것이면 const ref. 로 전달.

* 문제점
1. 상태를 나타내는 "데이터(Rect)"와 상태를 조작하는 "함수(getRectArea)" 를 분리되어 있다.
	: 데이터를 항상 함수의 인자로 전달해야 한다.
	: 사각형 관련 모든 함수는 인자로 Rect 를 받아야 한다.
	-> 구조체 안에 함수를 넣는다. 함수는 구조체 변수를 인자로 받지 않고 바로 사용할 수 있게된다.
	-> 함수들은 Rect 구조체 내부에 있는 것이므로, 함수명에 Rect 를 생략한다.
	* 데이터와 함수를 묶어서 타입을 설계하면
	* 보다 안전하고, 사용하기 쉬운 타입을 설계할 수 있다.
	*
	* 구조체 데이터	 : member data, field
	* 구조체 함수	 : member function, method

*/

#include <iostream>

struct Rect
{
	int left;	// x1
	int top;	// y1
	int right;	// x2
	int bottom;	// y2
};

int getRectArea(const Rect& r) // 사용자 정의 타입 인자는 참조로 전달받는다. const ref.
{
	return (r.right - r.left) * (r.bottom - r.top);
}

void drawRect(const Rect& r)
{
	std::cout << "DRAW RECT." << std::endl;
}

int main()
{
	Rect rc = { 1, 1, 10, 10 };
	int n = getRectArea(rc);
	drawRect(rc);
}

4.


/*
* 해결점
1. 사용자 지정 타입을 만든다. : 구조체 struct
2. 사용자 정의 타입을 인자로 전달할 때는 call by value 가 아닌, ref. 로 전달한다. 값 변경하지 않을 것이면 const ref. 로 전달.
3. 구조체 안에 함수를 넣는다. 함수는 구조체 변수를 인자로 받지 않고 바로 사용할 수 있게된다.

* 문제점
1. 멤버 데이터를 외부에서 직접 접근하면 객체가 잘못된 상태가 될 수 있다.
	: 멤버 데이터는 외부의 잘못된 사용으로 부터 보호하는 것이 안전하다.
	-> 접근 지정자 : private / public / protected
	- private : 멤버 함수에서만 접근 가능
	- public : 모든 함수에서 접근 가능
	- protected : 멤버 함수와 파생 클래스 멤버 함수에서 접근 가능. 상속 참고.

	* 캡슐화 (Encapsulation)
		- 멤버 데이터는 private 영역에 두어, 외부의 오용으로 부터 보호한다.
		- 멤버 데이터의 변경은 잘 정의된 규칙을 가진 멤버 함수를 통해서만 변경 가능하게 한다.
*/


#include <iostream>

struct Rect
{
	int left;	// x1
	int top;	// y1
	int right;	// x2
	int bottom;	// y2

	int getArea() // 구조체 변수를 바로 사용할 수 있다. 이름의 Rect 생략
	{
		return (right - left) * (bottom - top);
	}

	void draw()
	{
		std::cout << "DRAW RECT." << std::endl;
	}
};

int main()
{
	Rect rc = { 1, 1, 10, 10 };
//	int n = getRectArea(rc); // 사각형 rc 의 좌표를 던져줄테니 면적을 구해달라.
	int n = rc.getArea(); // 사각형 rc 의 면적을 구해달라.
	rc.draw(); // compile - draw(&rc)
}

5


/*
* 해결점
1. int type 변수 4개를 사용하여 코드가 복잡해진다.
	-> 사각형 타입이 없으므로, 사각형 한 개를 int 변수 4개로 표현하기 때문임
	-> 사각형 타입을 만든다. : 구조체 struct

2. struct 에  Call by Value 로 인수를 전달하여 "복사본 오버헤드"가 생긴다.
	-> 인자로 전달된 변수를 수정하지 않겠다는 약속이 있다.
	-> 그런데, 구조체 타입을 함수에서 인자로 전달될 때 Rect type data 크기만큼의 "복사본 오버헤드가 생긴다."
	-> 함수에서 복사하지 않고 참조로 인자를 받아 사용한다. : Reference - Rect& r
	-> 참조로 받을때 함수내에서 수정되지 않도록 : Const Refr. 로 받는다 - const Rect& r
	-> * 사용자 정의 타입을 인자로 전달할 때는 call by value 가 아닌, ref. 로 전달한다. 값 변경하지 않을 것이면 const ref. 로 전달.

3. 상태를 나타내는 "데이터(Rect)"와 상태를 조작하는 "함수(getRectArea)" 를 분리되어 있다.
	: 데이터를 항상 함수의 인자로 전달해야 한다.
	: 사각형 관련 모든 함수는 인자로 Rect 를 받아야 한다.
	-> 구조체 안에 함수를 넣는다. 함수는 구조체 변수를 인자로 받지 않고 바로 사용할 수 있게된다.
	-> 함수들은 Rect 구조체 내부에 있는 것이므로, 함수명에 Rect 를 생략한다.
	* 데이터와 함수를 묶어서 타입을 설계하면
	* 보다 안전하고, 사용하기 쉬운 타입을 설계할 수 있다.
	*
	* 구조체 데이터	 : member data, field
	* 구조체 함수	 : member function, method

4. 멤버 데이터를 외부에서 직접 접근하면 객체가 잘못된 상태가 될 수 있다.
	: 멤버 데이터는 외부의 잘못된 사용으로 부터 보호하는 것이 안전하다.
	-> 접근 지정자 : private / public / protected
	- private : 멤버 함수에서만 접근 가능
	- public : 모든 함수에서 접근 가능
	- protected : 멤버 함수와 파생 클래스 멤버 함수에서 접근 가능. 상속 참고.

	* 캡슐화 (Encapsulation)
		- 멤버 데이터는 private 영역에 두어, 외부의 오용으로 부터 보호한다.
		- 멤버 데이터의 변경은 잘 정의된 규칙을 가진 멤버 함수를 통해서만 변경 가능하게 한다.

* 문제점
1. struct vs class
	- struct : 접근 지정자 생략시 디폴트가 public. "모두 공개하고, 선택적으로 보호한다."
	- class  : 접근 지정자 생략시 디폴트가 private. "모두 보호하고, 선택적으로 공개한다."
	* 객체 지향에서는 class 의 사용이 더 올바르다.
	* C++ 에서 struct, class 의 차이는 위가 전부다.
*/

#include <iostream>
#include <string>

struct Person
{
private: // 변수 접근 방지
	std::string name;
	int age;

public: // 모든 함수에서 접근 가능. 외부(main)에서 접근가능
	void setAge(int value)
	{
		if ( value >= 1 && value < 150 )
			age = value;
	}
};

int main()
{
	Person p;

//	p.age = -10 //잘못된 사용, 바로 접근시 방어할 방법이 없다.
	p.setAge(-10);
}

6.


/*
* 해결점
1. int type 변수 4개를 사용하여 코드가 복잡해진다.
	-> 사각형 타입이 없으므로, 사각형 한 개를 int 변수 4개로 표현하기 때문임
	-> 사각형 타입을 만든다. : 구조체 struct

2. struct 에  Call by Value 로 인수를 전달하여 "복사본 오버헤드"가 생긴다.
	-> 인자로 전달된 변수를 수정하지 않겠다는 약속이 있다.
	-> 그런데, 구조체 타입을 함수에서 인자로 전달될 때 Rect type data 크기만큼의 "복사본 오버헤드가 생긴다."
	-> 함수에서 복사하지 않고 참조로 인자를 받아 사용한다. : Reference - Rect& r
	-> 참조로 받을때 함수내에서 수정되지 않도록 : Const Refr. 로 받는다 - const Rect& r
	-> * 사용자 정의 타입을 인자로 전달할 때는 call by value 가 아닌, ref. 로 전달한다. 값 변경하지 않을 것이면 const ref. 로 전달.

3. 상태를 나타내는 "데이터(Rect)"와 상태를 조작하는 "함수(getRectArea)" 를 분리되어 있다.
	: 데이터를 항상 함수의 인자로 전달해야 한다.
	: 사각형 관련 모든 함수는 인자로 Rect 를 받아야 한다.
	-> 구조체 안에 함수를 넣는다. 함수는 구조체 변수를 인자로 받지 않고 바로 사용할 수 있게된다.
	-> 함수들은 Rect 구조체 내부에 있는 것이므로, 함수명에 Rect 를 생략한다.
	* 데이터와 함수를 묶어서 타입을 설계하면
	* 보다 안전하고, 사용하기 쉬운 타입을 설계할 수 있다.
	*
	* 구조체 데이터	 : member data, field
	* 구조체 함수	 : member function, method

4. 멤버 데이터를 외부에서 직접 접근하면 객체가 잘못된 상태가 될 수 있다.
	: 멤버 데이터는 외부의 잘못된 사용으로 부터 보호하는 것이 안전하다.
	-> 접근 지정자 : private / public / protected
	- private : 멤버 함수에서만 접근 가능
	- public : 모든 함수에서 접근 가능
	- protected : 멤버 함수와 파생 클래스 멤버 함수에서 접근 가능. 상속 참고.

	* 캡슐화 (Encapsulation)
		- 멤버 데이터는 private 영역에 두어, 외부의 오용으로 부터 보호한다.
		- 멤버 데이터의 변경은 잘 정의된 규칙을 가진 멤버 함수를 통해서만 변경 가능하게 한다.

5. struct vs class
	- struct : 접근 지정자 생략시 디폴트가 public. "모두 공개하고, 선택적으로 보호한다."
	- class  : 접근 지정자 생략시 디폴트가 private. "모두 보호하고, 선택적으로 공개한다."
	* 객체 지향에서는 class 의 사용이 더 올바르다.
	* C++ 에서 struct, class 의 차이는 위가 전부다.

* 문제점
1. 구조체 생성시 데이터 초기화할 수 없다.
	-> 생성자(constructor) 와 소멸자(destructor)
	1.1. 생성자 
		- 클래스이름() 모양의 함수
		- 객체 생성시 자동 호출
		- 반환 타입을 표기하지 않고, 반환할 수 없다.
		- 인자가 없어도, 있어도 된다.
		- 2개 이상 만들 수 있다.
		- 생성자가 없으면 컴파일러가 디폴트 생성자를 제공한다.

	1.2. 소멸자
		- ~클래스이름() 모양의 함수
		- 객체 파괴시 자동 호출

*/

#include <iostream>
#include <string>

class Person // public -> class
{
//private: // class는 private 가 디폴트.
	std::string name;
	int age;

public:
	void setAge(int value)
	{
		if (value >= 1 && value < 150)
			age = value;
	}
};

int main()
{
	Person p;

	p.setAge(-10);
}

7.


/*
* 해결점
1. int type 변수 4개를 사용하여 코드가 복잡해진다.
	-> 사각형 타입이 없으므로, 사각형 한 개를 int 변수 4개로 표현하기 때문임
	-> 사각형 타입을 만든다. : 구조체 struct

2. struct 에  Call by Value 로 인수를 전달하여 "복사본 오버헤드"가 생긴다.
	-> 인자로 전달된 변수를 수정하지 않겠다는 약속이 있다.
	-> 그런데, 구조체 타입을 함수에서 인자로 전달될 때 Rect type data 크기만큼의 "복사본 오버헤드가 생긴다."
	-> 함수에서 복사하지 않고 참조로 인자를 받아 사용한다. : Reference - Rect& r
	-> 참조로 받을때 함수내에서 수정되지 않도록 : Const Refr. 로 받는다 - const Rect& r
	-> * 사용자 정의 타입을 인자로 전달할 때는 call by value 가 아닌, ref. 로 전달한다. 값 변경하지 않을 것이면 const ref. 로 전달.

3. 상태를 나타내는 "데이터(Rect)"와 상태를 조작하는 "함수(getRectArea)" 를 분리되어 있다.
	: 데이터를 항상 함수의 인자로 전달해야 한다.
	: 사각형 관련 모든 함수는 인자로 Rect 를 받아야 한다.
	-> 구조체 안에 함수를 넣는다. 함수는 구조체 변수를 인자로 받지 않고 바로 사용할 수 있게된다.
	-> 함수들은 Rect 구조체 내부에 있는 것이므로, 함수명에 Rect 를 생략한다.
	* 데이터와 함수를 묶어서 타입을 설계하면
	* 보다 안전하고, 사용하기 쉬운 타입을 설계할 수 있다.
	*
	* 구조체 데이터	 : member data, field
	* 구조체 함수	 : member function, method

4. 멤버 데이터를 외부에서 직접 접근하면 객체가 잘못된 상태가 될 수 있다.
	: 멤버 데이터는 외부의 잘못된 사용으로 부터 보호하는 것이 안전하다.
	-> 접근 지정자 : private / public / protected
	- private : 멤버 함수에서만 접근 가능
	- public : 모든 함수에서 접근 가능
	- protected : 멤버 함수와 파생 클래스 멤버 함수에서 접근 가능. 상속 참고.

	* 캡슐화 (Encapsulation)
		- 멤버 데이터는 private 영역에 두어, 외부의 오용으로 부터 보호한다.
		- 멤버 데이터의 변경은 잘 정의된 규칙을 가진 멤버 함수를 통해서만 변경 가능하게 한다.

5. struct vs class
	- struct : 접근 지정자 생략시 디폴트가 public. "모두 공개하고, 선택적으로 보호한다."
	- class  : 접근 지정자 생략시 디폴트가 private. "모두 보호하고, 선택적으로 공개한다."
	* 객체 지향에서는 class 의 사용이 더 올바르다.
	* C++ 에서 struct, class 의 차이는 위가 전부다.

6. 구조체 생성시 데이터 초기화할 수 없다.
	-> 생성자(constructor) 와 소멸자(destructor)
	1.1. 생성자 
		- 클래스이름() 모양의 함수
		- 객체 생성시 자동 호출
		- 반환 타입을 표기하지 않고, 반환할 수 없다.
		- 인자가 없어도, 있어도 된다.
		- 2개 이상 만들 수 있다.
		- 생성자가 없으면 컴파일러가 디폴트 생성자를 제공한다.

	1.2. 소멸자
		- ~클래스이름() 모양의 함수
		- 객체 파괴시 자동 호출

* 문제점
1. 클래스 선언에 멤버 함수의 '구현'을 포함
	-> 멤버 함수를 선언과 구현으로 분리한 후, "헤더파일(.h)과 소스파일(.cpp)" 로 분리해서 작성
	* 템플릿 사용시 반드시 헤더 파일에 멤버 함수 구현부도 있어야 한다. (linkage)
*/

#include <iostream>
#include <string>

class Person
{
	std::string name;
	int age;

public:
	//	void init() {} 
	Person() // 생성자, init. 
	{
		name = 'kim';
		age = 20;
	}
	
	Person(std::string str, int numb) //생성자2
	{
		name = str;
		age = numb;
	}

	~Person() // 소멸자 
	{
		std::cout << "Destructor" << std::endl;
	}

	void setAge(int value)
	{
		if (value >= 1 && value < 150)
			age = value;
	}
};

int main()
{
	Person p; //생성자 호출
	Person p2("hong", 18); //생성자2 호출
}// 소멸자 호출

8.

/*
* 해결점
1. int type 변수 4개를 사용하여 코드가 복잡해진다.
	-> 사각형 타입이 없으므로, 사각형 한 개를 int 변수 4개로 표현하기 때문임
	-> 사각형 타입을 만든다. : 구조체 struct

2. struct 에  Call by Value 로 인수를 전달하여 "복사본 오버헤드"가 생긴다.
	-> 인자로 전달된 변수를 수정하지 않겠다는 약속이 있다.
	-> 그런데, 구조체 타입을 함수에서 인자로 전달될 때 Rect type data 크기만큼의 "복사본 오버헤드가 생긴다."
	-> 함수에서 복사하지 않고 참조로 인자를 받아 사용한다. : Reference - Rect& r
	-> 참조로 받을때 함수내에서 수정되지 않도록 : Const Refr. 로 받는다 - const Rect& r
	-> * 사용자 정의 타입을 인자로 전달할 때는 call by value 가 아닌, ref. 로 전달한다. 값 변경하지 않을 것이면 const ref. 로 전달.

3. 상태를 나타내는 "데이터(Rect)"와 상태를 조작하는 "함수(getRectArea)" 를 분리되어 있다.
	: 데이터를 항상 함수의 인자로 전달해야 한다.
	: 사각형 관련 모든 함수는 인자로 Rect 를 받아야 한다.
	-> 구조체 안에 함수를 넣는다. 함수는 구조체 변수를 인자로 받지 않고 바로 사용할 수 있게된다.
	-> 함수들은 Rect 구조체 내부에 있는 것이므로, 함수명에 Rect 를 생략한다.
	* 데이터와 함수를 묶어서 타입을 설계하면
	* 보다 안전하고, 사용하기 쉬운 타입을 설계할 수 있다.
	*
	* 구조체 데이터	 : member data, field
	* 구조체 함수	 : member function, method

4. 멤버 데이터를 외부에서 직접 접근하면 객체가 잘못된 상태가 될 수 있다.
	: 멤버 데이터는 외부의 잘못된 사용으로 부터 보호하는 것이 안전하다.
	-> 접근 지정자 : private / public / protected
	- private : 멤버 함수에서만 접근 가능
	- public : 모든 함수에서 접근 가능
	- protected : 멤버 함수와 파생 클래스 멤버 함수에서 접근 가능. 상속 참고.

	* 캡슐화 (Encapsulation)
		- 멤버 데이터는 private 영역에 두어, 외부의 오용으로 부터 보호한다.
		- 멤버 데이터의 변경은 잘 정의된 규칙을 가진 멤버 함수를 통해서만 변경 가능하게 한다.

5. struct vs class
	- struct : 접근 지정자 생략시 디폴트가 public. "모두 공개하고, 선택적으로 보호한다."
	- class  : 접근 지정자 생략시 디폴트가 private. "모두 보호하고, 선택적으로 공개한다."
	* 객체 지향에서는 class 의 사용이 더 올바르다.
	* C++ 에서 struct, class 의 차이는 위가 전부다.

6. 구조체 생성시 데이터 초기화할 수 없다.
	-> 생성자(constructor) 와 소멸자(destructor)
	1.1. 생성자
		- 클래스이름() 모양의 함수
		- 객체 생성시 자동 호출
		- 반환 타입을 표기하지 않고, 반환할 수 없다.
		- 인자가 없어도, 있어도 된다.
		- 2개 이상 만들 수 있다.
		- 생성자가 없으면 컴파일러가 디폴트 생성자를 제공한다.

	1.2. 소멸자
		- ~클래스이름() 모양의 함수
		- 객체 파괴시 자동 호출

7. 클래스 선언에 멤버 함수의 '구현'을 포함
	-> 멤버 함수를 선언과 구현으로 분리한 후, "헤더파일(.h)과 소스파일(.cpp)" 로 분리해서 작성
	* 템플릿 사용시 반드시 헤더 파일에 멤버 함수 구현부도 있어야 한다. (linkage)

	* 문제점
*/

#include <iostream>
#include <string>

//===============================================================================================

//선언부 [Person.h]
 
// #pragma once //header include 2번 되는 것 방지.
class Person
{
	std::string name;
	int age;

public:
	Person(); // class 내부에 선언만 남긴다.
	Person(std::string str, int numb);
	~Person();
	void setAge(int value);
};

//===============================================================================================

// 구현부 [Person.cpp]

Person::Person() //#include "Person.h" //header file include 
{
	name = 'kim';
	age = 20;
}
Person::Person(std::string str, int numb)
{
	name = str;
	age = numb;
}
Person::~Person() 
{
	std::cout << "Destructor" << std::endl;
}
void Person::setAge(int value)
{
	if (value >= 1 && value < 150)
		age = value;
}

//===============================================================================================

// 메인부 [main.cpp]

//#include "Person.h" //class header file include
int main()
{
	Person p;
	Person p2("hong", 18);
}

//===============================================================================================
profile
Cool Kid Never Die

0개의 댓글