C++ 다중 상속과 추상 클래스를 활용한 도형 클래스 설계

객체지향 프로그래밍(OOP)에서 다중 상속은 하나의 파생 클래스가 여러 개의 기초 클래스로부터 특성을 물려받는 강력한 기능입니다. 이번 포스트에서는 좌표 정보를 가진 Point 클래스와 인터페이스 역할을 하는 추상 클래스 Plane을 기반으로 Circle 클래스를 구현하는 예제를 살펴보겠습니다.

1. 기초 클래스 설계

먼저 2차원 좌표를 표현하는 Point 클래스와 도형의 일반적인 속성인 둘레와 면적을 계산하기 위한 추상 클래스 Plane을 정의합니다.

#include <iostream>

using namespace std;

// 좌표를 관리하는 Point 클래스
class Point {
private:
    double x_pos;
    double y_pos;

public:
    Point(double x = 0, double y = 0) : x_pos(x), y_pos(y) {
        cout << "Point Constructor run" << endl;
    }

    Point(const Point& other) : x_pos(other.x_pos), y_pos(other.y_pos) {
        cout << "Point CopyConstructor run" << endl;
    }

    virtual ~Point() {
        cout << "Point Destructor run" << endl;
    }

    virtual void show() const {
        cout << "Point(X=" << x_pos << ",Y=" << y_pos << ")";
    }

    void setX(double x) { x_pos = x; }
    void setY(double y) { y_pos = y; }
    double getX() const { return x_pos; }
    double getY() const { return y_pos; }
};

// 도형의 계산 인터페이스를 제공하는 추상 클래스
class Plane {
public:
    virtual double length() const = 0; // 둘레 계산 (순수 가상 함수)
    virtual double area() const = 0;   // 면적 계산 (순수 가상 함수)
};

2. 다중 상속을 통한 Circle 클래스 구현

Circle 클래스는 Point로부터 중심 좌표 정보를 상속받고, Plane으로부터 수치 계산 인터페이스를 상속받아 구체화합니다. 원주율(PI)은 정적 데이터 멤버로 관리하여 메모리 효율성을 높입니다.

class Circle : public Point, public Plane {
protected:
    static const double PI;
private:
    double radius;

public:
    Circle(double x = 0, double y = 0, double r = 0) 
        : Point(x, y), radius(r) {
        cout << "Circle Constructor run" << endl;
    }

    Circle(const Circle& other) : Point(other), radius(other.radius) {
        cout << "Circle CopyConstructor run" << endl;
    }

    ~Circle() {
        cout << "Circle Destructor run" << endl;
    }

    void setR(double r) { radius = r; }
    double getR() const { return radius; }

    // 부모 클래스의 show()를 오버라이딩하여 원의 정보 출력
    void show() const override {
        cout << "Circle(";
        Point::show();
        cout << ",Radius=" << radius << ")" << endl;
    }

    // Plane 인터페이스 구현
    double area() const override {
        return PI * radius * radius;
    }

    double length() const override {
        return 2 * PI * radius;
    }
};

const double Circle::PI = 3.14159;

3. 다형성 활용 및 테스트

기초 클래스의 포인터나 참조자를 사용하면 파생 클래스의 객체를 유연하게 다룰 수 있습니다. 아래 테스트 코드는 가상 함수를 통해 런타임 다형성이 어떻게 작동하는지 보여줍니다.

void displayPointInfo(Point* p) {
    p->show();
}

void printLength(Plane* p) {
    cout << "Length=" << p->length() << endl;
}

void printArea(Plane& p) {
    cout << "Area=" << p.area() << endl;
}

int main() {
    double inputX, inputY, inputR;
    
    // 기본 생성 및 복사 생성 테스트
    Circle c1;
    Circle c2(c1);

    displayPointInfo(&c1);
    cout << endl;
    printArea(c1);
    printLength(&c1);

    // 사용자 입력에 따른 값 설정
    if (cin >> inputX >> inputY >> inputR) {
        c2.setX(inputX);
        c2.setY(inputY);
        c2.setR(inputR);
        
        displayPointInfo(&c2);
        cout << endl;
        printArea(c2);
        printLength(&c2);
    }

    return 0;
}

이 구조에서 Circle 클래스는 두 부모의 성질을 모두 가집니다. Point 포인터로는 좌표 정보를, Plane 포인터로는 기하학적 계산 기능을 호출할 수 있어 코드의 재사용성과 확장성이 극대화됩니다.

태그: cpp Object-Oriented Inheritance Polymorphism abstract-class

7월 26일 21:20에 게시됨