← 학습 코스

배송 요금의 두 방식

C++빈칸 채우기

객체마다 자기 값과 계산이 있어요

변수·함수·조건문을 알고 시작해요. 먼저 클래스와 객체를 구분한 뒤, 배송 요금에 연결하며 공통 계산을 이어받는 상속을 배워요.

함수에 가격을 전달해 요금을 구했던 것처럼, 클래스 안에도 가격 변수와 요금 함수를 둘 수 있어요. class Ticket은 Ticket이라는 새 자료형의 정의예요. 그 안에 둔 변수 price를 멤버 변수, 함수 cost를 멤버 함수라고 불러요.

class Ticket {
public:
    int price;
    int cost() { return price; }
};

여기까지는 자료형을 정의했을 뿐 실제 표를 만들지 않았어요. Ticket ticket;으로 만든 ticket이 객체예요. int count;가 정수 변수 count를 만드는 것처럼, Ticket 자료형으로 변수 ticket을 만든다고 읽어요. 클래스는 자료형, 객체는 그 자료형으로 만든 실제 대상이에요.

Ticket first;
Ticket second;
first.price = 10;
second.price = 7;

점 .은 그 객체의 멤버를 선택해요. first.price와 second.price는 서로 다른 저장 공간이에요. first.cost()는 first의 price를 읽어 10을, second.cost()는 second의 price를 읽어 7을 반환해요. public 아래의 멤버는 이처럼 객체 밖에서도 사용할 수 있어요. 위 예제는 price를 읽기 전에 값을 넣었어요.

상속하면 공통 부분을 이어받아요

이제 만들 때 가격을 넣도록 Ticket에 생성자를 두어요. 생성자는 클래스와 이름이 같은 함수이며 반환 자료형을 쓰지 않아요. Ticket ticket(10);을 실행하면 value로 10을 받아 ticket의 price를 초기화해요.

class Ticket {
public:
    int price;
    Ticket(int value) : price(value) {}
    int cost() const { return price; }
};

: 뒤의 price(value)는 멤버 price의 초기값을 value로 정하는 초기화 목록이에요. 뒤의 {}는 생성자의 함수 몸체예요. cost 뒤의 const는 이 함수가 그 객체의 일반 멤버 값을 바꾸지 않는다는 약속이에요. 여기서는 price를 읽기만 하므로 const를 붙일 수 있어요.

추가 요금 기능을 만들 때 가격 변수와 기본 요금 계산을 다시 쓰는 대신 Ticket을 이어받을 수 있어요. 상속을 제공하는 Ticket을 기반 클래스, 이어받는 ExtraTicket을 파생 클래스라고 불러요.

class ExtraTicket : public Ticket {
public:
    ExtraTicket(int value) : Ticket(value) {}
    int doubledCost() const { return price * 2; }
};

class ExtraTicket : public Ticket은 ExtraTicket이 Ticket을 public 상속한다는 선언이에요. ExtraTicket extra(7);의 value=7은 : Ticket(value)를 통해 기반 클래스 생성자에 전달돼요. 그래서 extra에도 price=7이 저장돼요.

extra.cost()는 이어받은 계산으로 7을 반환하고, extra.doubledCost()는 새로 둔 계산으로 14를 반환해요. 상속은 공통 부분을 이어받는 관계이고, 이 예제에서는 서로 다른 이름의 두 함수를 호출했어요. 같은 이름의 함수를 다르게 계산하는 경우는 다음 단계에서 봐요.

과제의 protected 멤버는 기반 클래스와 파생 클래스 안에서 사용할 수 있고 객체 밖에서는 직접 읽지 못해요. Delivery의 base가 protected여도 Express의 fee 안에서는 base를 읽을 수 있어요.

같은 호출에 다른 계산을 연결해요

앞 단계에서는 cost와 doubledCost라는 서로 다른 이름을 썼어요. 이번에는 두 종류 모두 cost라는 이름으로 요금을 물어보되, 실제 표의 종류에 맞는 계산을 실행해요.

기반 클래스의 cost에 virtual을 붙이면 파생 클래스의 계산으로 바꿔 호출할 수 있어요. 파생 클래스가 같은 이름·매개변수·const 여부로 함수를 정의하는 것이 오버라이드예요. override를 적으면 컴파일러가 그 관계가 맞는지도 확인해요.

class Ticket {
public:
    int price;
    Ticket(int value) : price(value) {}
    virtual int cost() const { return price; }
};
class ExtraTicket : public Ticket {
public:
    ExtraTicket(int value) : Ticket(value) {}
    int cost() const override { return price * 2; }
};
int readCost(const Ticket& ticket) {
    return ticket.cost();
}

Ticket&의 &는 이미 있는 객체를 복사하지 않고 참조한다는 뜻이에요. const는 이 참조로 객체의 값을 바꾸지 않도록 해요. 이 함수는 Ticket도, public 상속한 ExtraTicket도 같은 Ticket 형식으로 받아요.

Ticket normal(10); ExtraTicket extra(7);을 만든 뒤 readCost(normal)을 호출하면 Ticket의 cost가 실행되어 10을 반환해요. readCost(extra)는 ExtraTicket의 cost를 실행해 14를 반환해요. 매개변수에 Ticket이라고 적혀 있어도 virtual 호출은 실제 객체의 함수를 선택해요. 상속 관계를 만드는 것과 호출할 함수를 고르는 것은 다른 역할이에요.

과제에서는 같은 관계를 배송에 적용해요. Ticket 자리의 Delivery가 기본 요금을 계산하고, ExtraTicket 자리의 Express가 추가 요금을 계산해요. cost 대신 fee, readCost 대신 readFee라는 이름을 사용해요. 코드의 ~Delivery()는 객체 사용이 끝날 때 실행되는 소멸자예요. 생성자·참조 함수·소멸자는 과제에 제공된 형태를 사용해요.

기본료 10원, 거리 3, 추가 단가 2라면 일반은 10원, 빠른 배송은 16원이에요. 두 객체를 각각 readFee에 넘긴 합은 얼마일까요? 26원이에요.

직접 풀어봐요

일반 배송 요금은 base원이에요. 빠른 배송 요금은 기본료 base원에 distance×extra원을 더해요. 두 배송 객체의 요금 합을 반환하는 제공 코드의 빈칸을 채워요.

Express는 Delivery를 public 상속하고, fee를 재정의해 빠른 배송 요금을 반환해야 해요. base는 11000, distance는 0100, extra는 1~100이에요. 실행용 입력은 base distance extra, 출력은 solution의 반환값이에요. 생성자·readFee·main은 제공된 그대로 사용해요.

예시 1: (20,4,3) → 52. 일반 20원, 빠른 배송 32원이에요. 예시 2: (7,2,5) → 24. 일반 7원, 빠른 배송 17원이에요.

예시 입력

20 4 3

예상 결과

52

예시 입력

7 2 5

예상 결과

24
핵심 개념
  • oop-inheritance-poly: 클래스는 멤버 값과 함수를 묶어요. 상속은 공통 구현을 이어받고, virtual 함수의 override는 실제 객체의 계산을 선택해요.

코드 작성과 채점은 로그인 후 이용해요

로그인하고 풀기