#include <iostream>
#include <string>
using namespace std;
/**
* name, numClasses, classList 의 private 변수를 갖는 Class 를 생성.
* ========================= Private ============================
* name 은 string 타입
* classList 는 string 들이 들어있는 배열 이기 떄문에
* 포인터 형식으로 지정합니다. ` string * `
* numClasses는 classList 안에 있는 class들의 갯수 임으로 정수형 int type으로 정해줍니다.
* ======================== Public =============================
* string 매게변수를 갖는 생성자와, 아무것도 지정하지 않는 생성자가 있습니다.
* 소멸자 에서는 배열을 동적할당으로 넣어준 classList 의 연결을 끊어주기 위해
* delete [] 를 사용해줍니다.
*
* classList에서 각각의 class를 넣어주는 함수인 setClassList();
* classList에서 각각의 class를 출력해주는 함수인 setClassList();
* classList에서 각각의 class를 초기화 해주는 함수인 setClassList();
* Student 클래스의 깊은 복사를 위해 `대입연산자 = `를 오버라이딩 해줍니다.
**/
class Student {
public:
/** name = "", numClasses = 0, classList = NULL 로 인스턴스를 생성하는 생성자 **/
Student();
/** name = 매개변수 str 값 , numClasses = 0, classList = NULL 로 인스턴스를 생성하는 생성자 **/
Student(const string& str);
/** 시스템이 종료할 떄 classList 의 동적할당 메모리를 반환하기 위한 소멸자 **/
~Student();
/** classList 를 동적할당 하는 함수 **/
void setClassList();
/** name, classList 를 출력해주는 함수 **/
void getClassList();
/** classList 의 동적할당 메모리를 반환하고 관련된 변수를 초기화 하는 함수 **/
void clearClassList();
/** class 간 깊은 복사를 위한 오버라이딩, 매게변수로 들어온 class 로 깊은 복사가 된다 **/
Student& operator =(const Student& rightSide);
private:
string name;
int numClasses;
string *classList;
};
/**
* cin 과 getline(cin, string) 을 동시에 사용 하기 위한 함수
* 먼저 들어온 cin 에서 '\n' 을 getline 에 넘어가는 것을 막아준다.
**/
void newLine() {
char symbol;
do {
cin.get(symbol);
} while(symbol != '\n');
}
Student::Student() {
name = "";
numClasses = 0;
/** classList 는 포인터형 string 타입이기 떄문에 NULL 로서 초기화 해준다. **/
classList = NULL;
}
Student::Student(const string& str) {
name = str;
numClasses = 0;
/** classList 는 포인터형 string 타입이기 떄문에 NULL 로서 초기화 해준다. **/
classList = NULL;
}
Student::~Student() {
/** 시스템이 종료 할 떄, classList 의 동적할당 메모리를 반환 한다 **/
delete [] classList;
cout << "System is out" << endl;
cout << "Student " << name << " classList is delete" << endl;
}
/**
* 1. 사용자로 부터 동적할당의 크기를 입력 받는다.
* 2. 호출 인스턴스가 이미 할당을 받았으면, 입력된 만큼 추가로 동적할당을 받는다.
* 3. 호출 인스턴스가 이미 할당을 받지 않았으면, 입력된 만큼 동적할당을 받는다.
* 4. string 타입에서 '\0' 같은 빈공간 을 입력 받기 위해 getline() 함수를 사용한다.
* 5. 입력된 동적할당 크기 만큼 numClasses 를 설정해준다.
**/
void Student::setClassList() {
int size;
string className = "";
cout << "Enter the classListNumber \n";
cin >> size;
newLine();
if(numClasses > 0) {
for(int i = numClasses; i < size + numClasses; i++) {
classList = new string[size + numClasses];
cout << "Enter the class Name \n";
getline(cin, className);
classList[i] = className;
numClasses++;
}
} else {
classList = new string[size];
for(int i = 0; i < size; i++) {
cout << "Enter the class Name \n";
getline(cin, className);
classList[i] = className;
numClasses++;
}
}
}
/**
* 1. name 이 없으면, 사용자로 부터 name 을 입력 받는다.
* 2. 동적할당 사이즈인 numClasses 만큼 반복하며 classList 의 요소들을 출력한다.
**/
void Student::getClassList() {
if(name == "") {
cout << "what`s your name \n";
cin >> name;
}
cout << name << "`s classList \n";
for(int i = 0; i < numClasses; i++) {
cout << i + 1 << " - " << classList[i] << "\n";
}
}
/**
* 1. delete 명령어를 통해, 동적할당 메모리를 반환 해준다.
* 2. classList 의 값을 NULL 로 정해주고, numClasses 를 0 으로 해준다.
**/
void Student::clearClassList() {
delete [] classList;
classList = NULL;
numClasses = 0;
}
/**
* 1. 매게변수로 받은 Student class 인스턴스 와, 호출 class 인스턴스의 동적할당 메모리 사이즈인,
* numClasses 의 크기가 다르면, 호출 인스턴스를 초기화 시켜준다
* 2. 호출 인스턴스의 classList 를 새롭게 동적할당을 위해 new 명령어를 통해
* 매게변수 인스턴스의 numClasses 만큼의 사이즈를 갖는 배열을 생성해주고,
* 3. 그 후, numClasses 의 크기만큼 반복문을 통해서 호출 인스턴스의 classList 와 매게변수 인스턴스를 복사 해준다.
* 4. 그외 변수는 ' = ' 대입 연산자를 통해 변수를 지정해준다
* 5. 복사를 위한 ' = ' 오버라이딩 이기 때문에, *this 를 return 한다.
**/
Student& Student::operator=(const Student &rightSide) {
if(numClasses != rightSide.numClasses) {
clearClassList();
if(rightSide.numClasses > 0) {
numClasses = rightSide.numClasses;
classList = new string[rightSide.numClasses];
}
}
name = rightSide.name;
for(int i = 0; i < numClasses; i++) {
classList[i] = rightSide.classList[i];
}
return *this;
}
int main() {
/** 이름이 없는 인스턴스와, "Tim"을 이름으로 갖는 인스턴스를 생성 **/
Student std1, std2("Tim");
cout << "------ Setting 1st student's classList \n";
/** classList 를 설정해준다. // 2, a, b**/
std1.setClassList();
cout << "------ Getting 1st student's classList \n";
/** classList 를 출력 해준다. 위에서 설정한 값이 출력 된다. // 1 - a, 2 - b **/
std1.getClassList();
cout << "------ Getting 2nd student's classList \n";
/** classList 를 출력 해준다, 이름 출력후 아무것도 출력이 되지 않는다 **/
std2.getClassList();
cout << "------ 1st, 2nd copy \n";
/** 인스턴스를 복사해준다. **/
std2 = std1;
cout << "------ After copy Getting 2nd student's classList \n";
/** 복사 후, 아무것도 설정하지 않은 인스턴스를 출력하면 std1의 출력과 동일하다. **/
std2.getClassList();
cout << "------ Clearing 1st Student's ClassList \n";
/** std1를 초기화 해준다. 초기화를 하면 출력을 하였을때 아무것도 출력이 되지 않는다. **/
std1.clearClassList();
cout << "------ Getting 1st student's classList \n";
/** 출력을 하였을때 아무것도 출력이 되지 않는다. **/
std1.getClassList();
cout << "------ Getting 2nd student's classList \n";
/** std1은 출력이 안되지만, std2는 깊은 복사를 하였기 떄문에, std1의 동적할당 메모리가 반환되었다 하더라도
* 출력이 안되지는 않는다.
**/
std2.getClassList();
return 0;
}