2012-01-03 2 views
8

저는 보통 C#에서 프로그램을 작성하지만 약간의 C++을 시도하고 있으며 C++에서 인터페이스를 구현하려고 애 쓰고 있습니다.C++에서 인터페이스 구현하기

는 C#에서 나는 이런 식으로 뭔가 할 거라고 : C에서

class Base<T> 
{ 
    public void DoSomething(T value) 
    { 
     // Do something here 
    } 
} 

interface IDoubleDoSomething 
{ 
    void DoSomething(double value); 
} 

class Foo : Base<double>, IDoubleDoSomething 
{ 
} 

를 ++ 나는 이런 식으로 구현했습니다

template <class T> 
class Base 
{ 
public: 
    virtual void DoSomething(T value) 
    { 
     // Do something here 
    } 
}; 

class IDoubleDoSomething 
{ 
public: 
    virtual void DoSomething(double value) = 0; 
}; 

class Foo : public Base<double>, public IDoubleDoSomething 
{ 
}; 

문제는이 때문에 내가 푸를 인스턴스화 할 수 있다는 것입니다 추상 (DoSomething을 구현하지 않음). 나는 DoSomething을 구현할 수 있고 Base에 메서드를 호출 할 수 있다는 것을 알았지 만,이 작업을 수행하는 더 좋은 방법이 있기를 바랬습니다. 나는 다른 데이터 타입을 가지고있는베이스로부터 상속받은 다른 클래스들을 가지고 있으며, Base를 사용하지 않는 IDoubleDoSomething을 상속받은 다른 클래스들을 가지고있다.

도움을 주시면 감사하겠습니다.

+2

, 어떤 방법으로 그것은 "더 나은"수 :

그래서 다음과 같이 귀하의 예제 작업을 할 수 있습니다, 주어진? –

+2

"Foo"가 Base에서 메서드를 상속 받았으며 구현이 필요하지 않은 C# 버전과 같이 "더 나은"기능을한다고 가정합니다. Foo의 Base에서 각 메소드를 구현하는 데별로 나빠질 것이 없다고 생각합니다. 그냥 지저분 해 보입니다. – Clueless

+0

지저분하지만 더 좋은 방법을 찾지 못했습니다. ( –

답변

1

다른 사람들이 언급했듯이 기본 클래스의 두 함수는 공통 기본 클래스가 없으므로 (이름과 인수 유형이 같음에도 불구하고) 관련이 없습니다. 관계가 있기를 원하면 공통 기본 클래스를 제공해야합니다.

또한 일반적으로 다중 상속을 제대로 작동 시키려면 비공개 기본 클래스를 virtual으로 선언해야합니다. 그렇지 않으면 공통 기본 클래스를 사용하는 경우 (이 스타일의 코드에서 자주 필요함) 나쁜 일이 발생합니다.

template <class T> 
class IDoSomething { 
public: 
    virtual void DoSomething(T value) = 0; 
}; 

template <class T> 
class Base : public virtual IDoSomething<T> 
{ 
public: 
    virtual void DoSomething(T value) 
    { 
     // Do something here 
    } 
}; 

class IDoubleDoSomething : public virtual IDoSomething<double> 
{ 
}; 

class Foo : public virtual Base<double>, public virtual IDoubleDoSomething 
{ 
}; 
이 너무 나쁜 무엇
+0

이것은 내가 달성하려고했던 것과 가장 가까운 것으로 보이고, 'Base'를 소유하고 있기 때문에 제 시나리오에서는 잘 작동합니다. 만약 내가 'Base'의 주인이 아니라면 다른 솔루션을 더 적용 할 수있을 것 같습니다. – Clueless

2

은 당신이 IDoSomething1IDoSomething2을 구현하지 않고 Foo를 사용할 수있는 다음과 같은 C++ 코드를 C에서

class Foo 
{ 
public: 
    void DoSomething1(){} 
}; 

template<typename t> 
void MethodExpectsDosomething1(t f) 
{ 
    f.DoSomething1(); 
} 

template<typename t> 
void MethodExpectsDosomething2(t f) 
{ 
    f.DoSomething2(); 
} 

int main() 
{ 
    Foo f; 
    MethodExpectsDosomething1<Foo>(f); 

    MethodExpectsDosomething2<Foo>(f); 

    return 0; 
} 

++를 고려하십시오. 두 번째 방법 MethodExpectsDosomething2FooDoSomething2 메서드가 없어 컴파일되지 않습니다.

C#에서는 이러한 구조를 사용할 수 없으므로 IDoSomething1IDoSomething2 인터페이스가 있어야하며이를 type constraint으로 지정해야합니다.

코드를보고 그러한 인터페이스가 전혀 필요하지 않은지 확인해야 할 필요가 있습니다.

+0

오리 타이핑의 문제점은 자체 문서화가 아니라, 다형성 관련 솔루션이 자체 문서화하는 동안입니다 – akappa

+0

오리 입력이 그렇다면 나쁜 ... C# 4.0은 '동적'키워드로 도입하지 않았을 것입니다. 도끼를 주었기 때문에 다리를 자르지 않아도된다는 의미는 아닙니다. –

+0

인수가 "대중적이므로 그렇게 할 수 없습니다. 나쁜 것 "은 좋지 않은가? 만약 당신이 templatized 함수의 사용자라면, 당신의 객체로부터의 요청을 어떤 종류의 기능과 어떤 의미로 기능시키는지를 어떻게 알 수있을 것인가?이 문제는 동적 다형성에는 존재하지 않는다. 인터페이스가 문서이기 때문에. – akappa

-1

다른 모든 순서가 갖추어져 있다면,이 방법이 효과적입니다. 원래 코드 푸에

class Foo : public Base<double> 
{ 
}; 

2 무효 해봐요 (double 값) 방법 (1 추상적 인)을 가질 것이다. 기본 부분과 IDoubleDoSomething 부분이됩니다. Foo :: Base 및 Foo :: IDoubleDoSomething. 일시적으로 IDoubleDoSomething.DoSomething()에 구현하여 구현하여 시도해 볼 수 있습니다. 푸 이미 자료 "의"는 "이후

은 그러나 당신은 당신이 IDoubleDoSomething없이 필요가

+2

인터페이스를 사용하는 이유는 기본 클래스 나 파생 클래스를 정의하지 않아도 포인터를 전달하기 때문입니다. 인터페이스 클래스를 제거하면 역으로 진행됩니다. –

2
C++에서

가 순수 가상 함수는 항상 파생 클래스에서 재정의되어야한다. 그들은 다른 기지에서 재정의를 상속 할 수 없습니다 동적 다형성이 필요한 경우 함수를 호출하는 Foo 함수를 작성하는 합리적인 대안이 있다고 생각하지 않습니다. Base 함수는 가상 일 필요가 없습니다.

이러한 클래스를 사용하는 방법 (특히 인터페이스의 각 인스턴스 유형이 컴파일 타임에 알려진 것인지 여부에 따라 다름)에 정적 다형성을 사용하여 특정 구현 클래스를 사용자에게 주입 할 수 있습니다 템플릿 매개 변수로; 예를 들면 :

// No explicit interface specification with static polymorphism 
class Foo : public Base<double> 
{ 
    // Inherits DoSomething(double) 
}; 

// Template can used with any class that impelements a 
// "DoSomething" function that can accept a double. 
template <class DoubleDoSomething> 
void DoSomethingWithDouble(DoubleDoSomething & interface, double value) 
{ 
    interface.DoSomething(value); 
} 

// This particular specialisation uses a "Foo" object. 
Foo foo; 
DoSomethingWithDouble(foo, 42); 
2

건이며, Base::DoSomethingIWhatever::DoSomething 두 관련이없는 기능 (이 어떤 순수 가상 함수, 당신은 어쨌든 Foo 객체에 DoSomething를 호출 할 수 없을 것이되지 않은 경우에도 있습니다). 이 작업을 수행하려면 BaseIWhatever에서 상속되어야합니다.

실제로 이것이 필요한지 물어보십시오. 템플릿 (및 인터페이스와 같은 개념 인 일반적인 프로그래밍 - Boost.ConceptCheck 참조)은 일반적으로 런타임 하위 유형 다형성보다 C++에서 더 나은 솔루션입니다. (그래서 예를 들어 IDoSomething<double>의) 당신이 IDoubleDoSomething을 templatise 수있는 추가 보너스 포인트

template <typename T, class Interface> 
class Base : public Interface { ... }; 

class Foo : public Base<double, IDoubleDoSomething> { ... }; 

, 또는에 특성 클래스를 사용

2

귀하는이 인터페이스를 구현하는 자료에 두 번째 템플릿 매개 변수를 전달할 수 유형 T를 관련 인터페이스에 맵핑하십시오.

관련 문제