728x90
728x90

객체 배열 및 객체 포인터 배열은 C언어의 구조체 배열, 구조체 포인터 배열과 비슷하다.

 

객체 배열

객체 기반의 배열 선언하는 법을 본다.

SomSimple arr[10];
// SoSimple은 클래스 이름

 

동적 할당 객체 배열 선언

열 개의 SoSimple 객체가 모여서 배열을 구성하는 형태이다. 
구조체 배열과 형태가 같다.
배열을 선언하는 경우도 생성자는 호출된다

SoSimple * ptrArr=new SomSimple[10];

배열 선언과정에서는 호출할 생성자를 별도로 명시하지 못한다. (생성자에 인자를 전달하지 못한다)
위 형태로 배열이 생성되려면 SoSimple() { .... } 형태의 생성자가 반드시 있어야 한다.

SoSimple() { .... }

배열 선언 이후 각각의 요소를 원하는 값으로 초기화시키려면 일일히 초기화 과정을 거쳐야 한다.
이전 예제의 Person 클래스 기반의 예제로 객체 배열을 살펴본다.

 

객체 배열 예제

객체 배열 생성 시 void형 생성자가 호출되며, 배열 소멸시에도 그 배열을 구성하는 객체의 소멸자가 호출된다.

// ObjArr.cpp
#define _CRT_SECURE_NO_WARNINGS
#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]; //Person 3번
	char namestr[100];
	char* strptr;
	int age;
	int len;

	for (int i = 0; i < 3; i++) { //정보를 입력받아 객체 초기화
		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;
}

 

 

 

객체 포인터 배열

객체 배열은 객체로 이뤄진 배열,
객체 포인터 배열은 객체의 주소값 저장이 가능한 포인터 변수로 이뤄진 배열이다.

객체 포인터 배열 예제
// ObjPtrArr.cpp
#define _CRT_SECURE_NO_WARNINGS
#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]; // 객체의 주소값 3개를 저장할 수 있는 포인터 배열 선언
	char namestr[100]; 
	int age; 

	for (int i = 0; i < 3; i++) { //정보를 입력받아 객체 초기화
		cout << "이름 : ";
		cin >> namestr;
		cout << "나이 : ";
		cin >> age; 
	
		parr[i] = new Person(namestr, age); //객체를 생성 후 객체의 주소값을 배열에 저장
	}
	parr[0]->ShowPersonInfo();
	parr[1]->ShowPersonInfo();
	parr[2]->ShowPersonInfo();
	delete parr[0];
	delete parr[1];
	delete parr[2];
	return 0;
}

 

parr[i]=new Person(namestr, age); 객체를 생성 후 객체의 주소값을 배열에 저장
객체를 저장할 때에는 두가지 중 하나로 저장한다. (객체를 저장 vs 객체의 주소값을 저장)

 

 

this 포인터

멤버함수 내에서는 this 포인터를 사용할 수 있다.
this 포인터는 객체 자신을 가리키는 용도로 사용되는 포인터이다.

this 포인터 이해 예제

this는 객체자신의 주소값을 의미한다.
this포인터는 주소값과 자료형이 정해지지 않은 포인터다.

// PointerThis.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<iostream> 
#include<cstring> 
using namespace std;

class SoSimple
{
private:
	int num;
public:
	SoSimple(int n) : num(n)
	{
		cout << "num=" << num << ", ";
		cout << "address=" << this << endl;
	}
	void ShowSimpleData()
	{
		cout << num << endl;
	}
	SoSimple* GetThisPointer() //반환형이 포인터
	{
		return this; //문장을 실행하는 객체의 포인터 반환
	}
};
int main(void)
{
	SoSimple sim1(100);
	SoSimple* ptr1 = sim1.GetThisPointer(); //sim1 객체의 주소 값 저장
    // 객체 sim1에 의해 반환된 this는 SoSimple의 포인터이므로 SoSimple형 포인터변수에 저장
    
	cout << ptr1 << ", ";  //ptr1에 저장된 주소값 출력
	ptr1->ShowSimpleData();  
	
	SoSimple sim2(200);
	SoSimple* ptr2 = sim2.GetThisPointer(); //sim2 객체의 주소 값 저장
	cout << ptr2 << ", ";
	ptr2->ShowSimpleData();
	
	return 0;
}

 

 

this 포인터의 활용

같은 이름의 함수 매개변수, 객체 멤버변수를 this포인터를 활용하면 의도대로 사용할 수 있다.
객체를 참조하는 포인터 this의 특성 때문이다.

this->num=207;
// PointerThis.cpp
#include<iostream> 
using namespace std;

class TwoNumber
{
private:
	int num1;
	int num2;
public:
	TwoNumber(int num1, int num2) 
	{
	// 멤버변수 각각에 매개변수 각각을 저장한다.
		this->num1 = num1;
		this->num2 = num2;
	}
	// 멤버 이니셜라이저는 this 포인터를 사용할 수 없는 대신
	// 저장하는 변수는 멤버변수로, 저장되는 값은 매개변수로 인식해서
	// 이렇게도 사용할 수 있다. 
	/* TwoNumber(int num1, int num2)
	* : num1(num1), num2(num2)
	{ 
		//empty
	}*/
	void ShowTwoNumber()
	{
		cout << this->num1 << endl; //this포인터는 생략 가능
		cout << this->num2 << endl;
	}
};
int main(void)
{
	TwoNumber two(2, 4);
	two.ShowTwoNumber();
	return 0;
 }

 

점심먹고 여기부터

Self-Reference의 반환

Self-Reference는 객체 자신을 참조할 수 있는 참조자이다.
this포인터를 사용해서 객체가 자신의 참조에 사용할 수 있는 참조자의 반환문을 구성할 수 있다.

// SelfRef.cpp
#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; //객체 자신의 포인터가 아닌 객체 자신을 반환
		// this가 객체를 가리키는 포인터니까
		// this가 가리키는 곳 (포인터의 포인터) 즉 객체자신.
	}
	SelfRef& ShowTwoNumber()
	{
		cout << num << endl;
		return *this;
	}
};

int main(void)
{
	SelfRef obj(3);
	SelfRef& ref = obj.Adder(2); //참조자므로 obj에 별명붙인거

	obj.ShowTwoNumber();
	ref.ShowTwoNumber(); //그래서 같은 값

	ref.Adder(1).ShowTwoNumber().Adder(2).ShowTwoNumber(); //객체의 참조값을 반환해서 함수를 호출해서 가능
	return 0;
}

 

 

참조의 정보(참조 값)에 대한 이해

변수 num을 참조할 수 있는 참조 값이 참조자 ref에 전달되어, ref가 변수 num 을 참조하게 된다.

int main(void)
{
	int num=7;
	int &ref=num; //변수 num을 참조할 수 있는 참조의 정보가 전달된다.
	...
}

 

728x90
728x90

'C, C++ > 열혈 C++ 프로그래밍' 카테고리의 다른 글

05.복사생성자(copy constructor) (책)  (0) 2021.09.29
05.복사생성자  (0) 2021.09.28
04-03. 생성자와 소멸자(책)  (0) 2021.09.24
04. 클래스의 완성 연습문제  (0) 2021.09.23
3. 클래스의 기본  (0) 2021.09.15
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,

v