객체 포인터
객체의 주소 값을 가지는 변수
포인터로 멤버를 접근할 때 : 객체포인터 -> 멤버
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include <iostream>
using namespace std;
class Circle {
int radius;
public:
Circle() {
radius = 3;
}
Circle(int r) {
radius = r;
}
double getArea() {
return radius * radius * 3.14;
}
};
int main(void) {
Circle donut;
Circle* p = &donut; //객체에 대한 포인터 선언 및 객체 주소 저장
cout << "using pointer : " << p->getArea() << endl; //멤버 함수 호출
cout << "using *p : "<<(*p).getArea() << endl;
cout << "using parameter : " << donut.getArea() << endl;
return 0;
}
|
객체 배열
- 객체 포인터와 연결할 수 있음
- 객체의 멤버를 원하는 값으로 바꾸는 방법(void 생성자 호출 밖에 안됨)
- set() 멤버함수 구현하여 멤버변수값 변경
- 임시객체로 초기화
- 2차원 객체 배열
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#include <iostream>
using namespace std;
class Circle {
int radius;
public:
Circle() {radius = 3;} //void 생성자가 없다면 객체 배열 생성 시 에러가 발생한다.
Circle(int r) {
radius = r;
}
double getArea() {
return radius * radius * 3.14;
}
void setRadius(int r) { //set() 멤버함수 구현
radius = r;
}
};
int main(void) {
Circle arr[5];
Circle arr2[5] = { Circle(3), Circle(2), Circle(1), Circle(), Circle()}; //임시 객체로 초기화
Circle* p = arr; //배열의 이름이 포인터를 의미하기 때문에 이렇게 코드를 작성할 수 있다.
arr[2].setRadius(4); //멤버변수의 값을 4로 변경
cout << arr2[1].getArea() << endl; //배열명으로 접근
cout << p[1].getArea() << endl; //포인터로 접근
cout << (p + 2)->getArea() << endl; //화살표 연산자로 접근
cout << (*(p + 3)).getArea() << endl; //주소로 접근
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
//#. 2차원 배열
int main(void) {
Circle arr[2][3] = { {Circle(1), Circle(2), Circle(3)},{Circle(4), Circle(5), Circle(6)}};
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
cout << arr[i][j].getArea() << endl;
}
}
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
//#실습
#include <iostream>
using namespace std;
class Sample {
int a;
public:
Sample() { a = 100; cout << a << ' '; }
Sample(int x) { a = x; cout << a << ' '; }
Sample(int x, int y) { a = x * y; cout << a << ' '; }
int get() { return a; }
};
int main(void) {
Sample arr[3];
Sample arr2D[2][2] = { {Sample(2,3), Sample(2, 4)},{Sample(5), Sample()}};
Sample* p = arr;
int total = 0;
int total2D = 0;
for (int i = 0; i < 3; i++) {
total += (p + i)->get();
}
cout << endl << "첫번째 배열의 합은 " << total << endl;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
total2D += arr2D[i][j].get();
}
}
cout << "두번째 배열의 합은" << total2D << endl;
return 0;
}
|
동적 메모리 할당 및 반환
new / delete 키워드
new / delete 키워드를 통해 동적할당이 가능하다.
1
2
3
4
5
6
7
8
9
10
|
#include <iostream>
using namespace std;
int main(void)
{
char* cp = new char[4];
delete cp;
return 0;
}
|
1. 변수 동적 할당
1
2
3
4
5
6
7
8
9
|
//C style
int* p = (int *)malloc(sizeof(int));
*p = 10;
free(p);
//C++ style
int* p = new int;
*p = 10;
delete p;
|
2. 배열 동적 할당
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//C style
int* p = (int*)malloc(sizeof(int)*5);
free(p);
//C++ style
int* p = new int[5];
delete [] p;
char* p = new char[20];
delete [] p;
//값 할당하기
p[i] = 10;
*(p + i) = 20;
|
#. SIZE를 입력받아서 SIZE에 해당하는 배열 동적 할당
1
2
3
|
int size;
cin >> size;
int* p = new int[size];
|
#. company라는 문자열을 입력 받아 길이에 딱 맞는 배열을 동적 할당
1
2
|
int size = strlen("company") + 1;
char* p = new char[size];
|
- 정적 할당
- 변수 선언을 통해 필요한 메모리 할당, 많은 양의 메모리는 배열 선언을 통해 할당
- 동적 할당
- 필요한 양이 예측되지 않는 경우. 프로그램 작성 시 할당받을 수 없음.
- 실행 중에 운영체제로부터 할당 받음(heap으로부터 할당)
- C언어의 동적 메모리 할당
- malloc(), free() 라이브러리 함수 사용
-의 동적 메모리 할당/반환
- new, delete 연산자 사용
#. 클래스의 경우 동적 생성이라고도 표현한다.
#. delete 사용시 주의점
1
2
3
4
5
6
7
8
|
int n = 10;
int* p = &n;
delete p; //동적할당이 된 것이 아니므로 에러 발생
int* p = new int;
delete p;
delete p; //이미 할당이 해제되어 에러 발생
|
동적 할당 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include <iostream>
using namespace std;
int main(void)
{
int size;
double sum = 0;
cout << "입력할 정수의 개수는 ? ";
cin >> size;
int* p = new int[size];
for (int i = 0; i < size; i++) {
cout << i + 1 << "번째 정수 입력 : ";
cin >> p[i];
sum += p[i];
}
delete[] p;
cout << "평균 : " << sum / size << endl;
}
|
객체의 동적할당
1. 객체의 멤버변수를 동적할당할 때는 소멸자에서 메모리를 해제해야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
#include <iostream>
using namespace std;
// 객체의 멤버변수가 동적할당된 메모리의 주소를 지님
// 객체 생성 시 생성자에서 동적할당
// 객체가 소멸될 때 호출되는 소멸자에서 메모리 해제
class NameCard {
char* name;
char* comp;
char* tel;
char* pos;
public:
NameCard(const char* _name, const char* _comp, const char* _tel, const char* _pos) {
int name_size = strlen(_name) + 1;
int comp_size = strlen(_comp) + 1;
int tel_size = strlen(_tel) + 1;
int pos_size = strlen(_pos) + 1;
name = new char[name_size];
strcpy_s(name, name_size, _name);
comp = new char[comp_size];
strcpy_s(comp, comp_size, _comp);
tel = new char[tel_size];
strcpy_s(tel, tel_size, _tel);
pos = new char[pos_size];
strcpy_s(pos, pos_size, _pos);
}
~NameCard() {
delete[] name;
delete[] comp;
delete[] tel;
delete[] pos;
}
void ShowNameCardInfo() {
cout << "이름 : " << name << endl;
cout << "회사 : " << comp << endl;
cout << "전화 : " << tel << endl;
cout << "직급 : " << pos << endl;
cout << endl;
}
};
int main(void)
{
NameCard manClerk("Lee", "ABCEng", "010-000-444", "clerk");
NameCard manSenior("Hong", "OrangeEng", "010-333-4444", "senior");
NameCard manAssist("Kim", "SoGoodComp", "010-555-6666", "assist");
manClerk.ShowNameCardInfo();
manSenior.ShowNameCardInfo();
manAssist.ShowNameCardInfo();
return 0;
}
|
2. 객체 자체를 동적할당 할 경우 : main함수에서 메모리를 해제해줘야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#include <iostream>
using namespace std;
class Circle
{
int radius;
public:
Circle() { radius = 1; }
Circle(int r) { radius = r; }
double getArea() { return 3.14 * radius * radius; }
};
int main(void) {
//원의 반지름을 반복적으로 입력받아 Circle 객체 동적 생성하고 면적 출력
//음수가 입력되면 종료
int r;
while (1)
{
cout << "정수 반지름 입력(음수 입력 시 종료)";
cin >> r;
if (r < 0)
break;
//객체 동적 생성
Circle* p = new Circle(r);
cout << "원의 면적은 : " << p->getArea() << endl;
delete p;
}
return 0;
}
|
3. 객체 배열을 동적 생성할 때 : 역시 main함수에서 메모리 해제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#include <iostream>
using namespace std;
class Circle
{
int radius;
public:
Circle() { radius = 1; }
Circle(int r) { radius = r; }
double getArea() { return 3.14 * radius * radius; }
void setRadius(int _radius) {
radius = _radius;
}
};
int main(void) {
int n, rad;
int cnt = 0;
cout << "생성하고자 하는 원의 개수 : ";
cin >> n;
Circle* p = new Circle[n];
for (int i = 0; i < n; i++) {
cout << "원" << i + 1 << "의 반지름 : ";
cin >> rad;
p[i].setRadius(rad);
// *p[0].setRadius(10);
// (p + 1)->setRadius(20);
if (p[i].getArea() >= 100 && p[i].getArea() <= 200)
cnt++;
}
cout << "면적이 100에서 200 사이인 원의 개수는 " << cnt << "개 입니다." << endl;
delete[] p;
return 0;
}
|
this 포인터
- 자기참조 포인터(객체 안에서), 객체의 주소값을 가지는 변수
- 클래스의 멤버 함수 내에서만 사용
- 개발자가 선언하는 변수가 아니고, 컴파일러가 선언한 변수
- 멤버 함수에 컴파일러에 의해 묵시적으로 삽입 선언되는 매개 변수
멤버변수와 매개변수가 변수명이 같을 때
매개변수의 우선순위가 높기 때문에 멤버변수를 초기화할 수 없다. 이 때, 멤버변수를 this를 통해 접근할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#include <iostream>
using std;
class Circle
{
int radius;
public:
Circle() { radius = 1; }
Circle(int radius) { this->radius = radius; }
double getArea() { return 3.14 * radius * radius; }
void setRadius(int radius) {
this->radius = radius;
}
};
int main(void)
{
Circle waffle(30);
cout << waffle.getArea() << endl;
return 0;
}
|
멤버 함수가 객체 자신의 주소를 반환할 때
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
#include <iostream>
using namespace std;
class Circle
{
int radius;
public:
Circle() { radius = 1; }
Circle(int radius) { this->radius = radius; }
double getArea() { return 3.14 * radius * radius; }
void setRadius(int _radius) {
radius = _radius;
}
Circle* increase()
{
radius++;
return this;
}
Circle decrease() {
radius--;
return *this;
}
};
int main(void)
{
Circle pizza;
pizza.setRadius(10);
cout << pizza.getArea() << endl;
Circle* p = pizza.increase();
cout << p->getArea() << endl;
Circle tmp = pizza.decrease();
cout << tmp.getArea() << endl;
return 0;
}
|
제약사항
- 멤버 함수가 아닌 함수에서 this 사용 불가
- static 멤버 함수에서 this 사용 불가
- 객체가 생기기 전에 static 함수 호출이 있을 수 있기 때문에
string 클래스
문자열 처리를 위한 클래스이다. string은 객체이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#include <string>
int main(void)
{
// 1. 생성
string name = "kim";
string yourname(name);
string yourname1 = name;
string addr("서울 서초구 양재동");
// 2. 출력
cout << addr << endl;
// 3. 동적 생성
string* ptr = new string("C++");
delete ptr;
// 4. 입력
cin >> addr;
getline(cin, addr);
}
|
# string 클래스 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#include <iostream>
#include <string>
using namespace std;
// string배열에 5개의 문자열을 받고, 사전 구성에서 가장 뒤에 오는 문자열 출력
int main(void)
{
string arr[5];
for (int i = 0; i < 5; i++)
{
cout << "이름 >> ";
getline(cin, arr[i]);
}
// 최대값 구하기
string max = arr[0];
for (int i = 0; i < 5; i++)
{
if (max < arr[i]) {
max = arr[i];
}
}
cout << "사전에서 가장 뒤에 나오는 문자열은 " << max << endl;
return 0;
}
|
문자열을 다루기 위한 멤버함수(string 클래스)
- 문자열 비교
int compare(string & str) : 문자열과 str을 비교해서 같으면 0, str보다 앞에 있으면 음수, 뒤에 있으면 양수
비교연산 : >, <, >=, <=, =
- 문자열 연결
append() 함수 사용가능
- 문자열 삽입
insert(인덱스, 문자열) 함수 사용
- 문자열 바꾸기(치환)
replace(위치, 몇 개, “바꿀 문자열”) 함수 사용
- 문자열 길이 구하기
length() 함수, size() 함수
- 문자열 지우기
erase(위치, 몇개) 함수
- 문자열 추출
substr(위치, 몇개) 함수
- 문자 찾기
find(문자열) : 찾으면 위치 반환, 못 찾으면 -1 반환
- 문자를 숫자로 바꾸기
stoi() 함수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
// 1. 문자열 비교
string str1 = "kim";
string str2 = "lee";
if (str1.compare(str2) == 0)
cout << "같다" << endl;
else
cout << "아니다" << endl;
// 2. 문자열 연결
string str3 = "서울";
string str4 = " 양재동";
str3.append(" 서초구");
cout << str3 << endl;
string addr = str3 + str4;
cout << addr << endl;
// 3. 문자열 삽입
string str5 = "I love C++";
str5.insert(2, "really ");
cout << str5 << endl;
// 4. 문자열 바꾸기(치환)
str5.replace(2, 11, "study");
cout << str5 << endl;
// 5. 문자열 길이
cout << str5.length() << endl;
cout << str5.size() << endl;
// 6. 문자열 지우기
str5.erase(0, 8);
cout << str5 << endl;
str5.clear();
cout << str5 << endl;
// 7. 문자열 추출
string str6("I love C++");
string tmp = str6.substr(2, 4);
string tmp1 = str6.substr(2);
cout << str6 << endl;
cout << tmp << endl;
cout << tmp1 << endl;
// 8. 문자 찾기
int result = str6.find("love");
cout << str6.find("love") << endl;
result = str6.find("LOVE");
cout << result << endl;
// 9. string to integer
string year = "2023";
int n = stoi(year);
cout << typeid(n).name() << endl;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include <iostream>
#include <string>
using namespace std;
class Person {
string name;
string tel;
public:
string getName() {
return name;
}
string getTel() {
return tel;
}
void SetPerson(string name, string tel) {
this->name = name;
this->tel = tel;
}
};
int main(void)
{
Person people[3];
string name, tel;
cout << "사람이름 번호 순으로 입력하세요(공백으로 구분)" << endl;
for (int i = 0; i < 3; i++) {
cout << "사람 1 >> ";
cin >> name >> tel;
people[i].SetPerson(name, tel);
}
cout << "모든 사람의 이름은 ";
for (int i = 0; i < 3; i++)
{
cout << " " << people[i].getName();
}
cout << endl;
cout << "전화번호를 검색합니다. 이름을 입력해주세요 ";
cin >> name;
for (int i = 0; i < 3; i++)
{
if (name == people[i].getName() ){
cout << people[i].getTel() << endl;
}
}
return 0;
}
|