Coding Test/HackerRank

[C++/Classes] Virtual Functions

깐요 2022. 1. 15. 16:44

문제


Virtual Functions | HackerRank

 

Virtual Functions | HackerRank

Learn how to use virtual functions and solve the given problem.

www.hackerrank.com

기초 클래스인 Person 클래스와 파생 클래스인 Professor 클래스와 Student 클래스를 조건에 맞게 구현하는 문제입니다.

또한, 기초 클래스의 멤버 함수를 가상 함수로 구현하고, 파생 클래스에서 오버로드(Overload)를 거쳐 객체의 타입에 따라 다르게 동작하도록 구현하는 문제입니다.

 

풀이


int main(){

    int n, val;
    cin>>n; //The number of objects that is going to be created.
    Person *per[n];

    for(int i = 0;i < n;i++){

        cin>>val;
        if(val == 1){
            // If val is 1 current object is of type Professor
            per[i] = new Professor;

        }
        else per[i] = new Student; // Else the current object is of type Student

        per[i]->getdata(); // Get the data from the user.

    }

    ...

main 함수에서 변수 선언 부분을 살펴보면 파생 클래스(derived class)가 아닌 기초 클래스(base class) 객체의 포인터로 선언하고 있습니다.

이후 val 값에 따라 파생 클래스인 Professor 클래스와 Student 클래스로 동적으로 할당하고 있습니다.

...

class Person {
    private:
        string name;
        int age;
    public:
        void getdata() {
            cin >> name >> age;
        }
        void putdata() {
            cout << name << " " << age;
        }
};

...

이 상황에서 가상 함수를 사용하지 않고 Person 의 멤버 함수를 구현하면, 컴파일 시점에서 함수가 결정됩니다.
(정적 바인딩, Static binding)

따라서, per 의 각 요소는 파생 클래스를 가리키고 있지만, Person 객체의 포인트로 선언됐으므로, Person 클래스의 멤버 함수가 실행됩니다.

이러한 문제는 기초 클래스의 멤버 함수를 virtual 키워드를 통해 가상 함수로 선언해주면 해결됩니다.

        virtual void getdata() {
            cin >> name >> age;
        }
        virtual void putdata() {
            cout << name << " " << age;
        }

가상 함수로 선언하게 되면 컴파일 시점이 아닌 실행 시간(Runtime)에 함수가 결정되므로 (동적 바인딩, Dynamic binding), 객체의 실제 타입에 따라 성격이 바뀝니다.



class Professor : public Person{
    private:
        int publications;
        int cur_id;
    public:
        Professor() { cur_id = ++p_id; }
        void getdata () {
            Person::getdata();
            cin >> publications;
        }
        void putdata() {
            Person::putdata();
            cout << " " << publications << " " << cur_id << '\n';
        }
};

부모 클래스인 Person 의 멤버 변수들은 private 변수로 선언되어있으므로, nameage 변수를 직접적으로 사용할 수 없습니다.

따라서 Person 클래스의 멤버 함수를 호출해주어 부모 클래스의 변수를 다루었습니다.



int p_id = 0;   //professor id
int s_id = 0;   //student id

교수와 학생의 id 를 설정하기 위해 정적 변수를 사용했습니다.

각 클래스의 객체가 생성자가 호출될 때마다 id 값을 증가시키고 멤버 변수에 부여합니다.

 

전체 코드


#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

//Only Edit Here
//----------------------------------------
int p_id = 0;   //professor id
int s_id = 0;   //student id

class Person {
    private:
        string name;
        int age;
    public:
        virtual void getdata() {
            cin >> name >> age;
        }
        virtual void putdata() {
            cout << name << " " << age;
        }
};

class Professor : public Person{
    private:
        int publications;
        int cur_id;
    public:
        Professor() { cur_id = ++p_id; }
        void getdata () {
            Person::getdata();
            cin >> publications;
        }
        void putdata() {
            Person::putdata();
            cout << " " << publications << " " << cur_id << '\n';
        }
};

class Student : public Person{
    private:
        int marks[6];
        int cur_id;
    public:
        Student() { cur_id = ++s_id; }
        void getdata() {
            Person::getdata();
            for (int i = 0; i < 6; i++) {
                cin >> marks[i];
            }
        }
        void putdata() {
            int sum_marks = 0;
            for (int i = 0; i < 6; i++) {
                sum_marks += marks[i];
            }
            Person::putdata();
            cout << " " << sum_marks << " " << cur_id << '\n';
        }
};
//--------------------------------------

int main(){

    int n, val;
    cin>>n; //The number of objects that is going to be created.
    Person *per[n];

    for(int i = 0;i < n;i++){

        cin>>val;
        if(val == 1){
            // If val is 1 current object is of type Professor
            per[i] = new Professor;

        }
        else per[i] = new Student; // Else the current object is of type Student

        per[i]->getdata(); // Get the data from the user.

    }

    for(int i=0;i<n;i++)
        per[i]->putdata(); // Print the required output for each object.

    return 0;

}

 

참고


 

C++ 가상 함수(Virtual Function)

안녕하세요 열코입니다. 이번 시간에는 C++ 클래스의 가상 함수(Virtual Function)에 대해 알아보도록 하겠습니다. 가상 함수는 기본 클래스(상속되지 않은 클래스) 내에서 선언되어 파생 클래스에

yeolco.tistory.com

 

가상 함수 - 위키백과, 우리 모두의 백과사전

객체 지향 프로그래밍에서, 가상 함수(virtual function 또는 virtual method)는 상속하는 클래스 내에서 같은 시그니처의 함수로 오버라이딩 될 수 있는 함수 또는 메소드이다. 이 개념은 객체 지향

ko.wikipedia.org

 

320x100

'Coding Test > HackerRank' 카테고리의 다른 글

[C++/STL] Deque-STL  (0) 2022.01.16
[C++/Class] Abstract Classes - Polymorphism  (0) 2022.01.15
[C++/Classes] Exceptional Server  (0) 2022.01.15
[C++/Classes] Inherited Code  (0) 2022.01.09
[C++/Classes] Box it!  (0) 2022.01.09