C++ 초급 - 8. 객체지향 프로그래밍 (4 - 인터페이스 개념 (Interface))

2025. 2. 22. 15:44프로그래밍 언어/C++

📌 8.4 인터페이스 개념 (Interface)

C++에는 Java나 C#과 같은 interface 키워드는 존재하지 않지만,
추상 클래스(Abstract Class)를 활용하여 인터페이스 개념을 구현할 수 있다.
C++에서는 순수 가상 함수만 포함하는 클래스를 인터페이스(Pure Interface)로 사용하며, 이를 통해 다중 상속(Multiple Inheritance)과 다형성(Polymorphism)을 활용한 설계가 가능하다.


📌 1. 인터페이스의 정의

🔹 (1) C++에서의 인터페이스란?

  • C++에는 interface 키워드가 존재하지 않음.
  • 대신 순수 가상 함수(virtual 함수명() = 0;)만 포함하는 추상 클래스를 인터페이스로 사용.
  • 인터페이스는 메서드의 "명세"만 제공하고, 실제 구현은 파생 클래스에서 담당.

💡 기본 문법

class 인터페이스이름 {
public:
    virtual void 함수명() = 0;  // 순수 가상 함수
};

💡 예제: 기본 인터페이스 정의

class Drawable {
public:
    virtual void draw() = 0;  // 순수 가상 함수 (인터페이스 역할)
};
  • Drawable 클래스는 draw()라는 순수 가상 함수만 포함하며, 이를 구현하는 클래스가 반드시 재정의해야 함.
  • 인터페이스의 역할을 수행하며, 다형성(Polymorphism)을 지원.

📌 2. 추상 클래스를 통해 인터페이스를 구현하는 방법

🔹 (1) 인터페이스를 활용한 객체지향 설계

  • 인터페이스를 사용하면 구체적인 구현을 몰라도, 특정 동작을 수행하는 객체를 일관되게 다룰 수 있음.
  • 코드의 확장성을 높이고, 유지보수를 쉽게 만들어줌.

💡 예제: 인터페이스 활용

#include <iostream>

// 인터페이스 역할을 하는 추상 클래스
class Drawable {
public:
    virtual void draw() = 0;  // 순수 가상 함수
};

// 실제 구현 클래스
class Circle : public Drawable {
public:
    void draw() override { std::cout << "원을 그립니다." << std::endl; }
};

class Rectangle : public Drawable {
public:
    void draw() override { std::cout << "사각형을 그립니다." << std::endl; }
};

int main() {
    Drawable* shape1 = new Circle();
    Drawable* shape2 = new Rectangle();

    shape1->draw();  // ✅ "원을 그립니다."
    shape2->draw();  // ✅ "사각형을 그립니다."

    delete shape1;
    delete shape2;
    return 0;
}

🔹 출력 결과

원을 그립니다.
사각형을 그립니다.

💡 설명

  • Drawable은 순수 가상 함수만 포함하는 추상 클래스인터페이스 역할 수행.
  • Circle과 Rectangle은 Drawable을 상속받아 각각의 draw() 함수를 구현.
  • Drawable* shape1 = new Circle(); → 부모 클래스 포인터로 자식 객체를 다룰 수 있음 (다형성 활용).

📌 3. 다중 상속을 활용한 인터페이스 구현

🔹 (1) C++에서 다중 상속을 통한 인터페이스 구성

  • C++에서는 인터페이스를 다중 상속(Multiple Inheritance)할 수 있음.
  • 하나의 클래스가 여러 개의 인터페이스를 동시에 구현 가능.
  • class Derived : public Interface1, public Interface2 형태로 상속.

💡 예제: 다중 상속을 활용한 인터페이스 구현

#include <iostream>

// 첫 번째 인터페이스
class Printable {
public:
    virtual void print() = 0;
};

// 두 번째 인터페이스
class Saveable {
public:
    virtual void save() = 0;
};

// 다중 상속을 통한 인터페이스 구현
class Document : public Printable, public Saveable {
public:
    void print() override { std::cout << "문서를 출력합니다." << std::endl; }
    void save() override { std::cout << "문서를 저장합니다." << std::endl; }
};

int main() {
    Document doc;
    doc.print();  // ✅ "문서를 출력합니다."
    doc.save();   // ✅ "문서를 저장합니다."

    return 0;
}

🔹 출력 결과

문서를 출력합니다.
문서를 저장합니다.

💡 설명

  • Printable과 Saveable은 각각 인터페이스 역할을 하는 추상 클래스.
  • Document는 두 인터페이스를 동시에 구현 (public Printable, public Saveable).
  • doc.print(); → ✅ 다중 인터페이스에서 정의한 기능을 독립적으로 구현 가능.

📌 4. C++에서 인터페이스를 사용할 때의 주의점

🔹 (1) 다중 상속의 문제점과 해결 방법

  • C++의 다중 상속은 상속 충돌 문제를 일으킬 수 있음.
  • 부모 클래스가 같은 멤버 변수를 가질 경우, 충돌이 발생할 수 있음.
  • 가상 상속(virtual)을 사용하면 다중 상속 문제를 해결할 수 있음.

💡 예제: 다중 상속 문제 발생

class A {
public:
    int value;
};

class B : public A { };
class C : public A { };

class D : public B, public C {  // A가 두 번 상속됨 → 모호성 발생
};

int main() {
    D obj;
    // obj.value = 10;  // ❌ 오류 발생! (B::A와 C::A 중 어떤 것을 참조해야 할지 모호함)
    return 0;
}

🔹 컴파일 오류 발생

error: ambiguous access of 'value'

🔹 (2) virtual 키워드를 사용한 해결 방법

  • 가상 상속(virtual)을 사용하면 다중 상속 문제를 해결할 수 있음.
  • virtual을 사용하여 기본 클래스를 명확하게 지정할 수 있음.

💡 예제: 가상 상속으로 해결

class A {
public:
    int value;
};

class B : virtual public A { };  // 가상 상속 적용
class C : virtual public A { };  // 가상 상속 적용

class D : public B, public C { };

int main() {
    D obj;
    obj.value = 10;  // ✅ 모호성 문제 해결
    return 0;
}

🔹 결과

컴파일 성공!

💡 설명

  • B와 C에서 A를 virtual로 상속하여 D가 A를 한 번만 상속받도록 해결.

📌 5. 정리

개념 설명
C++에서 인터페이스 구현 추상 클래스(Abstract Class)와 순수 가상 함수를 활용
순수 인터페이스(Pure Interface) 순수 가상 함수만 포함하는 클래스
다중 상속을 활용한 인터페이스 class Derived : public Interface1, public Interface2 형태로 구현
다중 상속 문제 중복 상속으로 인한 충돌 발생 가능 (A가 두 번 상속되는 문제)
가상 상속 해결법 class B : virtual public A { }을 사용하여 상속 충돌 해결