C ++에서 "인터페이스"라는 용어


11

자바는 사이에 명확한 구분을하게 class하고 interface. (C #도 마찬가지라고 생각하지만 경험이 없습니다.) 그러나 C ++을 작성할 때 클래스와 인터페이스 사이에 언어로 구별되는 것은 없습니다.

결과적으로 나는 항상 인터페이스가 자바에서 다중 상속이 없다는 해결 방법으로 보았습니다. C ++에서 이러한 구별을 만드는 것은 임의적이며 의미가 없습니다.

나는 항상 "가장 명백한 방법으로 쓰기"접근 방식을 사용하는 경향이 있으므로 C ++에서 Java의 인터페이스라고하는 것을 얻습니다. 예 :

class Foo {
public:
  virtual void doStuff() = 0;
  ~Foo() = 0;
};

그리고 나는 대부분의 구현자가 Foo내가 쓸 공통 기능을 공유 하기로 결정했습니다 .

class Foo {
public:
  virtual void doStuff() = 0;
  ~Foo() {}
protected:
  // If it needs this to do its thing:
  int internalHelperThing(int);
  // Or if it doesn't need the this pointer:
  static int someOtherHelper(int);
};

그러면 이것이 더 이상 Java 의미의 인터페이스가 아닙니다.

대신 C ++에는 동일한 기본 상속 문제와 관련된 두 가지 중요한 개념이 있습니다.

  1. virtual 상속
  2. 멤버 변수가없는 클래스는 기본으로 사용될 때 추가 공간을 차지할 수 없습니다

    "기본 클래스 하위 오브젝트의 크기는 0 일 수 있습니다"

    참고

가능한 한 # 1을 피하려고하는 사람들 중-그것이 가장 깨끗한 디자인 인 시나리오는 거의 발생하지 않습니다. 그러나 # 2는 "인터페이스"라는 용어에 대한 이해와 C ++ 언어 기능 사이의 미묘하지만 중요한 차이점입니다. 이 결과로 나는 현재 (거의) C ++에서 "인터페이스"라고 절대 언급하지 않으며 기본 클래스와 크기 측면에서 이야기합니다. 나는 C ++의 맥락에서 "인터페이스"는 잘못된 이름이라고 말한다.

많은 사람들이 그런 구별을하지는 않지만 그것은 나의 관심을 끌었습니다.

  1. C ++의 "인터페이스"내에 (예를 들어 protected) 비 virtual기능이 존재 하도록함으로써 아무것도 잃어 버리지 않습니까? (제 느낌은 정반대입니다-공유 코드의 자연스러운 위치)
  2. 용어 "인터페이스"는 C ++의 의미 - 그것은 의미 않습니다 순수 virtual또는 공정없이 멤버 변수 여전히 인터페이스와 C ++ 클래스를 호출하는 것입니다?

C # 동일한 갖는 인터페이스 구현 단일 상속 다중 상속 Java와 같은, 그러나 사용함으로써 일반적인 확장 방법 은은 internalHelperThing거의 모든 경우에서 시뮬레이션 할 수있다.
Sjoerd

가상 구성원을 노출하는 것은 좋지 않습니다.
Klaim

~Foo() {}추상 클래스 의 대중 은 모든 상황에서 (거의) 오류입니다.
늑대

답변:


11

C ++에서 용어 "인터페이스는"단지이 하나의 널리 받아 들여진 정의를 - 당신이 그것을 사용하려고 할 때마다, 그래서 당신은 당신이 정확히 무엇을 의미하는지 말해야한다 - 가상 기본 클래스를 기본 구현, 헤더 파일, 일반 회원들과 함께 또는없이 임의의 클래스 등.

예제와 관련하여 : Java (및 C #과 유사)에서 코드는 아마도 우려의 분리를 암시합니다.

interface IFoo {/*  ... */} // here is your interface

class FooBase implements IFoo 
{
     // make default implementations for interface methods
}

class Foo extends FooBase
{
}

C ++에서는이 수행 할 있지만 강제하지는 않습니다. 그리고 멤버 변수가 없지만 일부 메소드에 대한 기본 구현이 포함 된 경우 클래스를 인터페이스로 호출하려면 그렇게하십시오. 그러나 대화하는 모든 사람이 의미를 알고 있는지 확인하십시오.


3
C ++ 프로그래머에게 "인터페이스"의 또 다른 의미 public.h파일 의 일부입니다 .
David Thornley

코드 예제는 어떤 언어입니까? 그것이 C ++이 되려는 시도라면 울고 자합니다 ...
Qix-MONICA WAS MISTREATED

@ Qix : 쉽게 유지하고 내 게시물을 다시 읽습니다 (코드가 Java로되어 있음을 분명히 나타냄) .2000 포인트 이상이있는 경우 내 게시물을 편집하여 동등한 C ++ 예제 코드를 추가하여 예제를 더 많이 만들 수 있습니다 명확한.
Doc Brown

그것이 자바라면 여전히 잘못이며 편집 할 수 없습니다. 변경할 문자가 충분하지 않습니다. Java는 구현 / 확장에 콜론을 사용하지 않으므로 C ++에서 시도했는지 궁금합니다.
Qix-MONICA WAS MISTREATED

@Qix : 구문적인 문제가 더 있으면 크리스마스 선물로 유지할 수 있습니다 :-)
Doc Brown

7

인터페이스가 개념적으로 구현 (인터페이스-소문자 'i')과 추상화 (인터페이스-대문자 'I'모두라는 개념의 의미를 혼동시키는 함정에 빠진 것처럼 들릴 것입니다. ).

예제와 관련하여 첫 번째 코드 비트는 클래스 일뿐입니다. 클래스 에는 행동에 대한 액세스를 가능하게하는 메소드를 제공한다는 점에서 인터페이스 있지만 , 클래스를 원하는 행동 유형을 나타내는 추상화 계층을 제공하는 인터페이스 선언의 관점 에서는 인터페이스 가 아닙니다. 도구. 귀하의 게시물에 대한 Doc Brown의 답변 은 내가 여기서 말하는 것을 정확하게 보여줍니다.

인터페이스는 종종 다중 상속을 지원하지 않는 언어의 "해결 방법"으로 선전되지만 어려운 사실보다 오해라고 생각합니다. 인터페이스는 클래스 간 기능 호환성을 제공하거나 클래스에 대한 구현 추상화를 제공하기 위해 상속되거나 조상이 필요하지 않다는 점에서 다중 상속과는 전혀 관련이 없습니다. 사실, 코드를 그렇게 구현하고 싶을 때 상속을 효과적으로 제거 할 수 있습니다. 전적으로 권장하지는 않지만 할 있다고 말하고 있습니다.해. 따라서 실제로는 상속 문제에 관계없이 인터페이스는 클래스 유형을 정의 할 수있는 수단을 제공하여 객체가 서로 통신 할 수있는 방법을 결정하는 규칙을 설정하므로 클래스가 지원하지 않는 클래스의 동작을 결정할 수 있습니다. 해당 동작을 구현하는 데 사용되는 특정 방법을 지시합니다.

C ++의 "인터페이스"내에 비가 상 함수 (예 : 보호되지 않은)가 존재하도록함으로써 아무것도 잃어 버리지 않습니까? (제 느낌은 정반대입니다-공유 코드의 자연스러운 위치)

순수한 인터페이스는 완전히 추상적입니다. 왜냐하면 정의가 공통 조상으로부터 그들의 행동을 상속받지 않았을 수도있는 클래스 간의 호환성 계약을 정의 할 수 있기 때문입니다. 구현시 구현 동작을 서브 클래스에서 확장 할 수 있는지 여부를 선택하려고합니다. 메서드가 아닌 경우 virtual나중에 하위 클래스를 만들어야한다고 결정하면 나중에 해당 동작을 확장 할 수 없습니다. 구현이 가상인지 아닌지에 관계없이 인터페이스는 자체적으로 동작 호환성을 정의하지만 클래스는 클래스가 나타내는 인스턴스에 대해 해당 동작의 구현을 제공합니다.

C ++에서 "인터페이스"라는 용어가 의미가 있습니까? 순수한 가상만을 의미합니까, 아니면 멤버 변수가없는 C ++ 클래스를 인터페이스로 호출하는 것이 공정합니까?

저를 용서하십시오.하지만 실제로 C ++로 심각한 응용 프로그램을 작성한 지 오래되었습니다. 인터페이스는 여기에서 설명했듯이 추상화 목적의 키워드라는 것을 기억합니다. 나는 어떤 종류의 C ++ 클래스를 인터페이스라고 부르지 않고 클래스가 위에서 설명한 의미 내에서 인터페이스를 가지고 있다고 말합니다. 그런 의미에서 용어는 의미가 있지만 실제로 상황에 따라 다릅니다.


1
인터페이스의 "동작"과 "존재"의 구분에 +1
Doc Brown

6

Java 인터페이스는 "해결 방법"이 아니며, 다이아몬드 상속과 같은 다중 상속 문제를 피하고 결합을 최소화하는 설계 방식을 장려하기위한 의도적 인 설계 결정입니다.

보호 된 메소드가있는 인터페이스는 "상속보다 컴포지션을 선호"해야하는 교과서 사례입니다. 이 섹션의 Sutter와 Alexandrescu의 뛰어난 C ++ 코딩 표준 에서 인용하려면 :

상속세를 피하십시오 : 상속은 C ++에서 두 번째로 긴밀한 결합 관계이며 우정에 이어 두 번째입니다. 단단한 커플 링은 바람직하지 않으며 가능하면 피해야합니다. 따라서 후자가 실제로 디자인에 도움이된다는 것을 알지 못하면 상속보다 구성을 선호합니다.

인터페이스에 도우미 기능을 포함 시키면 약간의 타이핑이 절약되지만 커플 링을 도입하여 길을 아프게 할 수 있습니다. 헬퍼 함수를 ​​분리하여 전달하는 것이 거의 항상 더 낫습니다 Foo*.

STL은 이에 대한 좋은 예입니다. <algorithm>컨테이너 클래스에있는 대신 가능한 많은 도우미 함수를 가져옵니다 . 예를 들어 sort()공용 컨테이너 API를 사용하여 작업을 수행하므로 STL 코드를 변경하지 않고도 자체 정렬 알고리즘을 구현할 수 있습니다. 이 설계는 STL이 부스트에 대해 아무것도 알 필요없이 부스트와 같은 라이브러리를 사용하여 STL을 교체하는 대신 STL을 향상시킵니다.


2

C ++의 "인터페이스"내에 비가 상 함수 (예 : 보호되지 않은)가 존재하도록함으로써 아무것도 잃어 버리지 않습니까? (제 느낌은 정반대입니다-공유 코드의 자연스러운 위치)

보호되지 않는 비가 상 메소드를 추상 클래스에 넣으면 서브 클래스를 작성하는 사람에게 구현이 필요하다고 생각할 것입니다. 그렇게하면 순수한 의미에서 인터페이스의 목적을 무효화 할 수 있습니다. 이는 인터페이스를 숨기는 베니어를 제공하는 것입니다.

이것은 하나의 규모에 맞는 답이없는 경우 중 하나이며, 결정을 내리기 위해 경험과 판단을 사용해야합니다. 완전히 가상 클래스의 모든 가능한 서브 클래스 Foo가 항상 protected 메소드의 구현이 필요 하다는 100 % 확신을 가지고 말할 수 있다면 bar(), Foo그것이 올바른 장소입니다. Baz필요하지 않은 서브 클래스 가 있으면 코드에 액세스 할 수 bar()없다는 사실에 따라 생활 Baz해야하거나 클래스 계층 구조를 재배치해야합니다. 전자는 좋은 습관이 아니며 후자는 처음에 올바르게 정렬하는 데 걸리는 몇 분보다 더 많은 시간이 걸릴 수 있습니다.

C ++에서 "인터페이스"라는 용어가 의미가 있습니까? 순수한 가상만을 의미합니까, 아니면 멤버 변수가없는 C ++ 클래스를 인터페이스로 호출하는 것이 공정합니까?

C ++ 표준의 10.4 절은 인터페이스를 구현하기 위해 추상 클래스 사용을 언급하지만 공식적으로 정의하지는 않습니다. 이 용어는 일반적인 컴퓨터 과학 상황에서 의미가 있으며, 유능한 사람은 " Foo(무엇이든지)의 인터페이스 " 는 어떤 형태의 추상화를 의미한다는 것을 이해해야합니다 . 정의 된 인터페이스 구성을 가진 언어에 노출 된 사람들은 순수한 가상으로 생각할 수 있지만 실제로 작업해야하는 사람 Foo은 계속 진행하기 전에 해당 정의를 살펴볼 것입니다.


2
순수한 가상 선언과 선언 + 구현의 차이점은 무엇입니까? 두 경우 모두 구현 baz이 있어야하며 항상 return false;또는 그 와 같은 구현을 가질 수 있습니다 . 메소드가 모든 서브 클래스에 적용되지 않는 경우, 어떤 형태의 기본 추상 클래스에도 속하지 않습니다.
David Thornley

1
마지막 문장은 우리가 같은 페이지에 있다고 말합니다. 추상 클래스에서 메소드를 보호 할 수없는 이유는 없지만 상속 트리에서 절대적으로 필요한 것보다 높으면 안됩니다. 클래스가 구현을 더미 해야하는 경우 트리의 올바른 위치에 있지 않다고 생각합니다.
Blrfl
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.