2015-01-24 5 views
0

이 질문을하거나 여러 상속이 잘못되었다고 나에게 잘못 말하지 마십시오. 이 질문은 C++ 컴파일러가 작동하는 방식을 더 잘 이해하는 것입니다. inline 문은 컴파일러에게 함수 호출을 소스 코드로 대체하기 위해 컴파일러에게 모든 옵션을 포함하거나 포함하지 말 것을 알리는 데 사용됩니다. 만약 당신이 좋은 수 inline 기능을 강제 수 있지만 정말 해결하기 위해 노력하고 문제가되지 않습니다. 내가하고 싶은 일은 하나의 장소에서 작성되고 컴파일러가 다른 장소에서 복사하여 붙여 넣는 코드 한 장을 생성 할 수있게하는 것입니다. 이 코드는 내가 쓰기는 다음과 같이 보일 것입니다 :다중 상속을 사용하여 가상으로 인라인하는 방법

struct base 
{ 
    virtual double eval() = 0; // should be no eval function for the 
}; 

struct foo : public base 
{ 
    virtual double eval() overrides 
    { 
      return //foo eval 
    } 
}; 

struct bar : public base 
{ 
    virtual double eval() overrides 
    { 
      return //foo eval 
    } 
}; 

struct baz : public base 
{ 
    virtual double eval() overrides 
    { 
      return //baz eval 
    } 
}; 

struct FooBarBaz : public foo, public bar, public baz 
{ 
    virtual double eval() final 
    { 
      return foo::eval() + bar::eval() + baz::eval(); 
    } 
}; 

컴파일러는이에 상응하는 무언가 생성 할 것이다 : 나는 <type_traits>을 사용하여이 문제되는 경우를 해결하는 방법이라고 들었다

struct base 
{ 
    virtual double eval() = 0; // should be no eval function for the 
}; 

struct foo : public base 
{ 
    virtual double eval() overrides 
    { 
      return //foo eval 
    } 
}; 

struct bar : public base 
{ 
    virtual double eval() overrides 
    { 
      return //foo eval 
    } 
}; 

struct baz : public base 
{ 
    virtual double eval() overrides 
    { 
      return //baz eval 
    } 
}; 

struct FooBarBaz : public foo, public bar, public baz 
{ 
    virtual double eval() final 
    { 
      return /*foo eval*/ + /*bar eval*/ + /*baz eval*/ 
    } 
}; 

을 원하는 결과를 얻는 방법을 알고 싶습니다. 그렇지 않은 경우이 작업을 수행하는 방법을 알고 싶습니다.

+2

컴파일러가 이미 원하는 것을 수행하고 있는지 아십니까? 최적화 수준을 설정 한 다음 어셈블리 언어 목록을 살펴 보았습니까? –

+1

용서해주십시오.하지만 어떻게합니까? '상속 된'코드가 다중 상속과 다르게 작동하는 것을 상상하십니까? –

+0

나는 컴파일러에 중립적이며 어셈블러 언어에 대해 잘 알고있다. 'inline' 코드의 경우 컴파일러는 기본 함수 호출에서 코드를 사용하여 코드를 가져 와서 v-table을 통해 함수를 검색하는 대신 코드를 붙여 넣습니다. –

답변

1

컴파일러가 인라인으로 결정했는지 여부는 코딩 된 휴리스틱 스에 달렸는지 여부에 관계없이 foo::eval, bar::eval 및으로 호출을 인라인하면 안됩니다. baz::eval에서 FooBarBaz::eval 자격으로 인해 동적 발송이 비활성화됩니다.

즉 컴파일러가 foo::eval 호출을 만날 때 해당 멤버 함수에 대한 최종 재정의자를 foo 수준으로 실행합니다. 그것은 FooBarBaz 유형의 3 하위 객체를 가지고, 그보다 최종 overrider이 FooBarBaz::eval이 될 것이기 때문에, 어쨌든 무한 재귀에 끝날 것 vtable (.

다른, 당신은 약 가상 상속을 읽어야 사용하지 않습니다 base, 아마 당신이 원하는 게 아니 겠지 ...

+0

당신이 대답하는 것을 좋아하지만'base' 함수는 어떤 순수한 추상 인터페이스도 제공하지 않는 순수 추상 함수입니다 구현 또는 데이터를 파생 된 모든 객체에 전달하므로 _virtual inheritance_가 필요하지 않으면 _virtual inheritance_는 적합하지 않습니다. –

+0

@vickoza :'FooBarBaz fbz; 베이스 & b = fbz'.오류 : 두 개 이상의'base'가 있으므로 모호한 변환입니다. 어떤 것을 바인딩합니까? 인터페이스로 사용되는 빈베이스는'가상'상속의 주된 후보입니다 : 완전한 객체가 있고 다른 상속 경로를 통해 동일한 인터페이스를 구현하는 경우, 프로토콜을 구현하는 * 객체 만 있습니다. –

+0

고맙습니다. 이제 저는 가상 상속이 기본 구현을 병합한다고 생각합니다. 많은 객체를 공유하고있는 경우에는 하나의 기본 객체 만 가질 수 있습니다. 동일한 기본 구조를 가지므로 여러분은 확실히 struct FooBarBaz를 정의하고 있습니다 : public virtual foo, public virtual bar, public virtual baz'가 상속을 사용하는 것보다 가상 상속을 사용하는 것이 항상 좋은 생각이라면 –