객체 배열
: 객체를 기반으로 객체 배열의 선언이 가능하다.
클래스 이름이 SoSimple일 때, 객체 기반의 배열을 다음과 같이 선언한다.
SoSimple arr[10];
동적 할당
SoSimple * ptrArr = new SoSimple[10];
이러한 형태의 배열 선언은, 열개의 SoSimple 객체가 모여서 배열을 구성하는 형태이다.
이 경우에도 생성자는 호출이 되나, 배열 선언과정에서는 호출할 생성자를 별도로 명시하지 못한다. (생성자에 인자를 전달하지 못함)
위와 같이 객체 기반 배열이 생성되려면 다음 형태의 생성자가 반드시 정의되야 하낟.
So Simple() { . . . .}
#include <iostream>
#include <cstring>
using namespace std;
class Person
{
private:
char * name;
int age;
public:
Person(char * myname, int myage)
{
int len = strlen(myname) + 1;
name = new char[len];
strcpy(name, myname);
age = myage;
}
Person() // 배열 생성시 필요한 생성자 정의
{
name = NULL;
age = 0;
cout << "called Person()" << endl;
}
void SetPersonInfo(char * myname, int myage) // 초기화 함수
{
name = myname;
age = myage;
}
void ShowPersonInfo() const
{
cout << "이름: " << name << ", ";
cout << "나이: " << age << endl;
}
~Person()
{
delete[]name;
cout << "called destructor!" << endl;
}
};
int main(void)
{
Person parr[3]; // 객체 기반 배열의 선언
char namestr[100];
char * strptr;
int age;
int len;
for (int i = 0; i<3; i++) // for문을 통해 이름, 나이 입력받아서 객체를 초기화
{
cout << "이름: ";
cin >> namestr;
cout << "나이: ";
cin >> age;
len = strlen(namestr) + 1;
strptr = new char[len];
strcpy(strptr, namestr);
parr[i].SetPersonInfo(strptr, age);
}
parr[0].ShowPersonInfo();
parr[1].ShowPersonInfo();
parr[2].ShowPersonInfo();
return 0;
} |
Output :
called Person()
called Person()
called Person()
이름: 가가가가가가
나이: 1
이름: 나나나나나나나나
나이: 2
이름: 다다다다다다다다다
나이: 3
이름: 가가가가가가, 나이: 1
이름: 나나나나나나나나, 나이: 2
이름: 다다다다다다다다다, 나이: 3
called destructor!
called destructor!
called destructor!
객체 포인터 배열
: 객체의 주소 값 저장이 가능한 포인터 변수로 이뤄진 배열
#include <iostream>
#include <cstring>
using namespace std;
class Person
{
private:
char * name;
int age;
public:
Person(char * myname, int myage)
{
int len = strlen(myname) + 1;
name = new char[len];
strcpy(name, myname);
age = myage;
}
Person()
{
name = NULL;
age = 0;
cout << "called Person()" << endl;
}
void SetPersonInfo(char * myname, int myage)
{
name = myname;
age = myage;
}
void ShowPersonInfo() const
{
cout << "이름: " << name << ", ";
cout << "나이: " << age << endl;
}
~Person()
{
delete[]name;
cout << "" << endl; // 소멸자 호출과 delete 연산을 확인하기 위함
}
};
int main(void)
{
Person * parr[3]; // 객체 포인터 배열 선언
char namestr[100];
char * strptr;
int age;
int len;
for (int i = 0; i < 3; i++)
{
cout << "이름: ";
cin >> namestr;
cout << "나이: ";
cin >> age;
parr[i] = new Person(namestr, age); // 객체를 생성해, 주소값을 배열에 저장
}
for (int i = 0; i < 3; i++)
{
parr[i]->ShowPersonInfo();
delete parr[i]; // new 연산을 한만큼 delete 연산 진행
}
return 0;
} |
Output :
이름: 가가가가, 나이: 22
이름: 나나나나나, 나이: 33
이름: 다다다다다다다, 나이: 44
이름: 가가가가, 나이: 22
이름: 나나나나나, 나이: 33
이름: 다다다다다다다, 나이: 44
this 포인터의 이해
: 멤버 함수 내에서 객체 자신을 가리키는 용도로 사용되는 포인터
#include <iostream>
#include <cstring>
using namespace std;
class SoSimple
{
int num;
public:
SoSimple(int n) : num(n) // 생성자, 멤버 이니셜라이저 int num=n;
{
cout << "num=" << num << ", ";
cout << "address=" << this << endl;
}
void ShowSimpleData()
{
cout << num << endl;
}
SoSimple * GetThisPointer()
{
return this;
// this를 반환. 이는 this가 가리키는 객체의 포인터를 반환하라는 의미로, 반환형이 SoSimple * 형
}
};
int main(void)
{
SoSimple sim1(100);
SoSimple * ptr1 = sim1.GetThisPointer(); // sim1 객체의 주소값을 * ptr1 에 저장
cout << ptr1 << ", "; // ptr1에 저장된 주소값 출력
ptr1->ShowSimpleData(); // ptr1이 가리키는 객체의 ShowSimpleData 함수 호출
SoSimple sim2(200);
SoSimple * ptr2 = sim2.GetThisPointer();
cout << ptr2 << ", ";
ptr2->ShowSimpleData();
return 0;
}
|
this는 객체 자신을 가리키며, 위치한 객체내에서 자료형과 주소 값이 결정된다.
0xffeb3708에 할당된 sim1 객체 내에서는 this는 sim1 형의 포인터이면서 그 주소 값은 0xffeb3708 이 된다.
this 포인터 활용
객체의 주소 값으로 접근가능한 대상은 멤버 변수이다.
따라서 this->num1은 멤버 변수 num1을 의미한다.
위의 생성자는 아래의 같은 형태의 생성자로 대신할 수도 있다.
// this 포인터가 아닌 이니셜라이저를 통한 초기화 예
1 2 3 4 5 6 | TwoNumber (int num1, int num2) : num1(num1), num2(num2) // 이니셜라이저의 괄호안 num1은 매개변수 num1을 의미 { // empty } | cs |
멤버 이니셜라이저에서는 this포인터 사용불가.
Self-Reference의 반환
: 객체 자신을 참조할 수 있는 참조자
this포인터를 이용해, 객체가 자신의 참조에 사용할 수 있는 참조자의 반환문을 구성 가능
#include <iostream>
using namespace std;
class SelfRef
{
private:
int num;
public:
SelfRef(int n) : num(n)
{
cout << "객체생성" << endl;
}
SelfRef& Adder(int n)
{
num += n;
return *this; // 이는 객체 자신의 포인터가 아닌 객체 자신을 반환
// 함수의 반환형이 참조형(SelfRef &)이므로 객체 자신을 참조할 수 있는 참조자 반환
}
SelfRef& ShowTwoNumber()
{
cout << num << endl;
return *this;
}
};
int main(void)
{
SelfRef obj(3);
SelfRef &ref = obj.Adder(2); // 객체 obj의 참조값을 반환, 참조자 ref가 객체 obj의 참조자가 됨
obj.ShowTwoNumber();
ref.ShowTwoNumber();
ref.Adder(1).ShowTwoNumber().Adder(2).ShowTwoNumber();
return 0;
}
|
34행에서 객체 ref의 Adder함수가 호출. Adder함수는 참조값을 반환하므로, 반환된 참조 값을 가지고 ShowTwoNumber 함수 호출이 가능하다.
마찬가지로 ShowTwoNumber가 반환하는 참조 값을 이용해 다시금 함수를 이어서 호출 할 수 있게 된다.
이는 두 함수 Adder, ShowTwoNumber가 객체의 참조 값을 반환하기 때문에 가능하다.
'Study > C++' 카테고리의 다른 글
const, friend, static, mutable 선언 (0) | 2016.09.29 |
---|---|
복사 생성자, 얕은 복사와 깊은 복사, 임시 객체 (0) | 2016.09.28 |
생성자와 소멸자, 클래스 (0) | 2016.09.26 |
class (0) | 2016.09.25 |
CPP-Object Oriented Programming (객체지향 프로그래밍) (0) | 2016.09.23 |