C++에서도 오고야 말았다.. Class!
파이썬때도 살짝 맛 봤었으나 매콤했던 걸로 기억하는데..
OOP를 위해선 어쩔 수 없이 익숙해져야 하는 클라스!! 클래스!!
Classes
Class는 C++의 메인 Key point다.
전체적인 느낌은 Python과 유사하다.
여러 object를 만들기위한 청사진을 만드는 느낌
Class는 크게 2가지 정보를 저장한다.
1. Attributes : 데이터의 전체적인 정보, type
2. Method : 메쏘드라고 불리우며, data가 행할 수 있는 function들이다.
Objects
- 말 그대로 class의 object이다. Instance라고도 불리며, class로부터 받은 data attribute와 method를 encapsulate하고 있는 객체이다.
Class의 Structure
Class의 Definition
- Simple Vector라는 예시를 통해 Class의 정의 / 동작을 확인해보자
#include <iostream>
using namespace std;
class SimpleVector{
public:
int* array; //points to elements
int size; // # of elements
int capacity; // capa of array
SimpleVector(int initialCapacity):
size(0),capacity(initialCapacity){
array = new int[capacity]; // array dynamic 할당
}
~SimpleVector(){
delete[] array;
}
void addElement(int element){
if(size == capacity)
resize();
array[size] = element;
size++;
}
void resize(){
capacity = capacity * 2;
int* newArray = new int[capacity];
for(int i=0;i<size;i++)
newArray[i] = array[i];
delete[] array;
array = newArray;
}
int getSize(){
return size;
}
};
int main(){
SimpleVector vec(10);
vec.addElement(5);
cout << vec.getSize() << endl;
//1
}
뭐라뭐라 적긴했는데, 솔직히 잘 모르겠다.
차근차근 알아가보자
- SimpleVector vec 와 같은 Local Variable의 Memory는 Stack에 쌓인다.
- 참고로 pointer의 경우 어떤 종류의 값을 가르키는 pointer 건, 해당 포인터의 Memory는 8byte를 차지한다.
- Class 안에서 method를 쓸 때는 namespace / class name을 사용하지 않아도 된다.
- 그리고 Python의 self처럼 C++에선 this 를 사용할 수 있다.
- Class 밖 ( ex) main 함수 안 ) 에선 Namespace, classname 등을 특정해주고 dot(.) operator를 써서 method를 호출한다.
Constructors
- Initializer list이고 특별한 method이다. --> class와 같은 이름을 갖는다 + class 만들 때 자동호출
- Class 내에서 선언과 동시에 attribute들에 initial 값을 할당한다.
SimpleVector(int initialCapacity):
size(0),capacity(initialCapacity){
array = new int[capacity]; // array dynamic 할당
}
- 위는 return이 없는 구조이고, size는 0, capacity도 initialCapacity로 초기화 해주라는 initializer list이다.
- 위에서, string str; declare 시 일단 빈 string str이 만들어진다. 그 다음 initializer로 initStr이라는 값이 할당되는 구조이다.
- 문제는 없지만, 뭔가 변수에 값을 집어 넣는 것이 2 - step이 되는 구조라 비효율적이다(Poor!)
- 첫 번 째 OK Case는 괜찮지만, value 값은 class 내에서 const로 정의되었기에 값에 변동이 생기면 안 된다. 그래서 두 번 째에 value값을 다시 바꾸려하니 Error 발생.
- Initialize 부분에서 { value = ~ , str = ~ } 부분은 Body라고 부른다.
SimpleVector(std::initializer_list<int> elements)
: size(0), capa(elements.size()){
array = new int[capa];
for(auto element : elements){
addElement(element);
}
- std::initializer_list를 이용해서 Constuctor 초기화 부분을 setting할 수도 있다.
- 첫 번째 코드, 복잡한 initialize는 const body에 넣자.
- 두 번 째 코드, 이게 Error를 피할려면
1. Constructor에 아예 정의를 하지 않는다.
2. Constructor에 아무런 input을 받지 않는 것을 정의한다.
int main(){
SimpleVector vec;
SimpleVector vec(10);
SimpleVector vec = {1,2,3};
SimpleVector vec{1,2,3};
}
- 요런 4가지 방법으로 class를 소환할 수 있다.
Destructors
- Desturctor는 object의 명이 다했을 때, resoure를 정리해주는 역할을 한다.
- Class 하나 당 destructer는 하나만 정의될 수 있다.
~SimpleVector(){
delete[] array;
}
- Destructor가 call되는 순간
1. An automatic object가[ on - stack ] scope에서 벗어나는 순간 --> function return
2. A dynamic object [ on - heap ] 의 memory가 delete 함수로 사라질 때
등등
Other Methods
- resize 함수에서 new 부분은 Dynamic memory 할당이니까 HEAP Memory로 data가 저장된다.
- resize --> 기존 array 삭제(memory)시키는 컨셉. New Array에 기존 array data를 복붙 한 뒤에 말이다~~
- 그리고 Stack에 저장되어 있던 array의 Capa update! *array 값 update! (heap으로 할당해놨던 것) --> 기존 array의 heap memory는? Delete~~~
- int getSize() 에서 const는 요 함수에선 variable 변화는 없다고 compiler에게 일러 주는 것 --> 코드 효율화
Access Specifiers
1. Public : 선언된 Member들은 어느 Interface에서도 접근이 가능하다.
2. Protected : 선언된 Member들은 class 안, 상속받은 class 등에서만 접근이 가능하다. (대충 가까운 사이만 접근 가능하다는 느낌)
3. Privated : class 안(Within class) 외에는 접.근.불.가.
- Private 문구는 attribute / method의 의도치 않은 수정을 방지해주고, interface를 깔끔하게 해준다. for user(abstraction)
- 요렇게 한 class 안에서도 private / public 부분을 나눠서 attribute / method를 정의할 수 있다.
- Public method에서도 private에 접근이 가능하다. 한 Class 안에 같이 있는 것이라면!
Class Templates ( Very Very Important !!)
- 위에서 지금까지 정의했던 SimpleVector는 int element 값만을 받는다.
- 만약에 다른 type value를 받는 SimpleVector를 또 만들려면 class를 복제해서 또또또 만들어줘야 한다.
(벌써 풍기는 비효율의 냄새..)
- T는 class 안에서 any data type을 뜻하게 된다.
- T여도 pointer는 * 표시 해줘야 한다.
- T와 함께라면..
int main(){
SimpleVector<int> intvec(10);
SimpleVector<double> douvec(10);
SimpleVector<string> strvec(10);
}
- 어떤 데이터 타입의 vector도 소환이 가능하다. 그저 원하는 data type만 specific하게 선언해주면 되는 것
- Template을 사용하면..
- Compiler는 각 instance들을 template 조합에 따라 분리된 코드로 관리한다.
- Template의 장점!
1) Reusability : 코드 하나만 써 놓으면 다양한 data type에 활용 가능
2) Performance : Template code가 컴파일되면, 특정 data type에 맞게 optimization이 발동!
3) Maintainability : 코드의 수정 / 업데이트가 아무래도 편하다
4) Type Safety : Pointer 사용을 줄일 수 있다. --> error 감소
Template Example
- vector<T> , map<K,V> 이런 것들도 알고보면다 템플릿이다!
와.. 진짜 공부한다고 내용 복습하면서도 이게 대체 무슨 소린지 모르겠다.
처음 접할 땐 나중에 언젠가 이해가 되겠지.. 하면서 위로했는데
두 번 째로 내용을 훑는 지금도 솔직히 머리에 내용이 와닿게 들어오지 않는다.
너무 개념 위주로 때려서 그런가..
실습투입으로 좀 긴박성을 줄 필요가 있겠다 ㅠㅠ
'SW 만학도 > C++ & Algorithm' 카테고리의 다른 글
7. Copy&Move, Special Members (2) | 2024.04.12 |
---|---|
6. Out_of_class Definition & Operator Overloading (0) | 2024.04.10 |
4. Functions and Memory Management (1) | 2024.03.29 |
3. C++ Standard Library (3) (1) | 2024.03.24 |
2. C++ Standard Library (2) (1) | 2024.03.22 |