c++ 10.4

Jaewoong2·2020년 11월 20일
0

C++

목록 보기
8/13
#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;
}
profile
DFF (Development For Fun)

0개의 댓글