have to do_yeon
[C++ / OOP_lec08] Class & Object (3) 본문
1. Const (상수)
말 그대로 변수나 함수에 붙여주면 상수가 된다. 일반 변수에 붙여도 되고 포인터에 붙여도 된다. 마음대로~
자신과 가장 가까운 것을 상수화한다. 순서를 헷갈리지 말아야 하는데... 예제로 확인해보도록 하자.
#include <iostream>
using namespace std;
int main() {
int a = 100;
int b = 200;
// non const 포인터
int* ptr = &a;
ptr = &b; // 주소 변경 가능
*ptr = 300; // 값 변경 가능
// 상수 포인터(const pointer)
int* const ptr2 = &a;
ptr2 = &b; // error! 포인터가 상수이므로 변경 불가능
*ptr2 = 300; // 값은 변경 가능
// 상수에 대한 포인터
const int* ptr3 = &a;
ptr3 = &b; // 포인터가 상수가 아니므로 변경 가능
*ptr3 = 300; // error! 가리키는 값이 상수이므로 변경 불가능
// 상수에 대한 상수 포인터
const int* const ptr2 = &a;
ptr4 = &b; // error! 포인터가 상수이므로 변경 불가능
*ptr4 = 300; // error! 가리키는 값이 상수이므로 변경 불가능
}
(코드를 직접 쓰고 싶었지만, 이해좀요... 너무바쁨) 출처 >> https://coding-factory.tistory.com/660
자료형을 무시하고 가장 가까운 포인터나 변수를 상수화 함을 알 수 있다.
함수에 적용한 예제를 확인해보자.
#include <iostream>
using namespace std;
class MyClass {
private:
int var;
public:
void func1() const {
// func2(); // error!
func3();
}
void func2() {
var = 1;
}
void func3() const {
cout << var << endl;
}
};
int main() {
MyClass cons;
cons.func1(); // var 주소값 출력
}
const를 non-const로 불러오는 것은 가능하지만, non-const를 const로 불러오는 것은 불가능하다.
함수를 const 화 하면 멤버변수가 변하지 않는다는 뜻이다.
2. Copy Constructor (복사 생성자)
복사생성자를 명시적으로 정의하지 않으면 멤버 대 멤버의 복사를 진행하는 디폴트 복사생성자가 자동으로 만들어진다.
#include <iostream>
using namespace std;
class Person {
public:
int age;
Person(int a) : age(a) {}
// Person(const Person& other) : age(other.age) { } // create by the complier
};
int main() {
Person kim(21);
Person clone = kim;
cout << "Kim's age : " << kim.age << endl; // Kim's age : 21
cout << "Clone's age : " << clone.age << endl; // Clone's age : 21
return 0;
}
아래는 강의노트에 있는 예제를 가져왔다.
#include <iostream>
#include <string>
using namespace std;
class MyClass {
public:
string name;
MyClass(){ // 매개변수 없으면 디폴트
cout << "[ " << name << " ]";
cout << "Default Constructor..." << endl;
}
MyClass(const string& str) {
name = str;
cout << "[ " << name << " ]";
cout << "Constructor for string..." << endl;
}
MyClass(const MyClass& obj) {
name = obj.name;
cout << "[ " << name << " ]";
cout << "Copy Constructor..." << endl;
}
};
void func1(MyClass obj) { }
void func2(MyClass& obj) { }
MyClass func3(MyClass& obj) { return obj; }
MyClass& func4(MyClass& obj) { return obj; }
int main() {
MyClass obj1;
obj1.name = "Class #1"; // [ ]Default Constructor...
cout << endl;
MyClass obj2(obj1);
obj2.name = "Class #2";
cout << endl;
cout << "<Function #1>" << endl;
func1(obj1); // [ Class #1 ]Copy Constructor...
cout << endl;
cout << "<Function #2>" << endl;
func2(obj1); //
cout << endl;
cout << "<Function #3>" << endl;
auto obj3 = func3(obj1); // [ Class #1 ]Copy Constructor...
cout << endl;
cout << "<Function #4>" << endl;
auto& obj4 = func4(obj1); //
cout << endl;
return 0;
}
나도 잘 모르겠다 애초에 클래스부터 다시 공부해야하는 걸지도... 어우 하기싫어
예제는 한번씩 쳐보는게 좋을 듯 하긴 하다.
3. Shallow Cpoy VS Deep Copy
Shallow Copy란, 객체를 직접 대입하는 경우 참조에 의한 할당이 이루어진다. 따라서 둘은 데이터(주소)가 같다.
Deep Copy란, 아예 새로운 객체를 새로운 메모리 공간에 복사 해서 사용하는 것이다.
4. static (정적 변수)
개인적으로 강의자료가 잘 이해가 가지 않는다.
#include <iostream>
void incrementAndPrint()
{
static int s_value = 1; // 'static' 키워드를 사용한 '정적 생명 주기', 이 줄은 한번만 실행된다.
++s_value;
std::cout << s_value << '\n';
} // s_value는 여기서 소멸되지 않지만, 접근할 수 없게된다.
int main()
{
incrementAndPrint(); // 2
incrementAndPrint(); // 3
incrementAndPrint(); // 4
}
출처 >> https://boycoding.tistory.com/169
위 프로그램에서 s_value는 static으로 선언되었기 때문에 s_value는 한 번만 생성되고 1로 초기화된다.
지역변수로 선언되었지만 전역변수 취급하는 느낌인 것 같다.
5. vector (벡터 라이브러리)
벡터는 배열(array)과 비슷한데, 배열은 처음에 정한 배열의 크기를 직접 늘리지 않으면 늘어나지 않는 정적 배열임에 반해, 벡터는 데이터를 추가함에 따라 자동적으로 늘어나는 동적 배열이다.
#include <vector>
vector<int> vec; // 벡터 선언 = vector<자료형> 이름;
배열의 크기가 작거나, 간단한 문제들이라면 array를 사용해도 충분하지만, 배열의 크기가 동적으로 변해야한다면 vector를 활용하자.
라이브러리 내 다양한 함수들이 있으니 확인해보자.
>> http://www.cplusplus.com/reference/vector/vector
중요한 함수 몇가지만 살펴보자.
size() | 벡터 사이즈 리턴 |
max_size() | 현재 할당된 크기 리턴 |
capacity() | 현재 메모리 크기 리턴 |
reserve() | 인위적으로 크기 할당 |
push_back(값) | 마지막 부분에데이터 삽입 |
pop_back(값) | 마지막 데이터 삭제 |
insert(위치, 변수) | 데이터 원하는 곳 삽입 |
erase(위치) | 원하는 데이터 삭제 |
clear() | 모든 데이터 지우기 |
6. Operator Overloading (연산자 중복)
string의 경우, +연산자를 사용하여 두 문자열을 이을 수 있다.
이와같이 원래의 연산자가 아님에도 불구하고, 다른 객체에 대해서도 적용할 수 있도록 새로 정의하는 것을 의미한다.
대입연산자마저도 가능하다.
예제는 강의노트를 참고하자.
#include <iostream>
using namespace std;
sturct Vector {
double x;
double y;
double z;
}
Vector operator+(const Vector &v1; const Vector &v2) {
return { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
}
int main() {
Vector v1 = {1, 2, 3};
Vector v2 = {4, 5, 6};
auto v3 = v1 + v2;
cout << "(" << v3.x << v3.y << v3.z << ")" << endl;
// (5, 7, 9)
return 0;
}
나머지 두 강을 올릴지 말지 고민이다. 혼자 공부하는게 빠를거같은데
'Supplementary > OOP (1-2)' 카테고리의 다른 글
[C++ / OOP_lec07] Class & Object (2) (0) | 2022.10.22 |
---|---|
[C++ / OOP_lec06] Class & Object (1) (0) | 2022.10.22 |
[C++ / OOP_lec05] C part in C++ (4) (0) | 2022.10.11 |
[C++ / OOP_lec04] C part in C++ (3) (0) | 2022.09.27 |
[C++ / OOP_lec03] C part in C++ (2) (0) | 2022.09.27 |