문제
Virtual Functions | HackerRank
기초 클래스인 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 변수로 선언되어있으므로, name 과 age 변수를 직접적으로 사용할 수 없습니다.
따라서 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;
}
참고
'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 |