2010-05-11 2 views
3

이전 클래스에서 새 클래스를 파생하려고합니다. 기본 클래스 선언은 다음과 같습니다C++에서 모호한이 포인터 해결

그것의 생성자는 다음과 같습니다
class Driver : public Plugin, public CmdObject 
{ 
protected: 
    Driver(); 

public: 
    static Driver* GetInstance(); 
    virtual Engine& GetEngine(); 
public: 
    // Plugin methods... 
    virtual bool InitPlugin (Mgr* pMgr); 
    virtual bool Open(); 
    virtual bool Close(); 

    // CmdObject 
    virtual bool ExecObjCmd(uint16 cmdID, uint16 nbParams, CommandParam *pParams, CmdChannelError& error); 

    Mgr *m_pMgr; 

protected: 
    Services *m_pServices; 
    Engine m_Engine; 
}; 

:

Driver::Driver() : 
    YCmdObject("Driver", (CmdObjectType)100, true), 
    m_Engine("MyEngine") 
{ 
    Services *m_pServices = NULL; 
    Mgr *m_pMgr = NULL; 
} 

내 파생 클래스를 만들 때, 내가 먼저 간단하게 기본 클래스에서 상속하려고 :

class NewDriver : public Driver 

생성자 복사

NewDriver::NewDriver() : 
    CmdObject("NewDriver", (EYCmdObjectType)100, true), 
    m_Engine("MyNewEngine") 
{ 
    Services *m_pServices = NULL; 
    Mgr *m_pMgr = NULL; 
} 

컴파일러 (의 VisualDSP ++ 5.0 아나 로그 디바이스는)이 마음에 들지 않았다 감각을했다, 그래서 나는 직접 플러그인 및 CmdObject에서 상속하기로 결정

".\NewDriver.cpp", line 10: cc0293: error: indirect nonvirtual base 
     class is not allowed 
CmdObject("NewDriver", (EYCmdObjectType)100, true), 

. 다중 상속 모호성 문제를 (내가 생각) 방지하기 위해, 나는 가상 상속 사용 :

class NewDriver : public Driver, public virtual Plugin, public virtual CmdObject 

을하지만, NewDriver에서 가상 메소드의 구현에, 나는 걸리는 관리인 :: RegisterPlugin 메서드를 호출 시도 * 플러그인, 나는이있어 :

".\NewDriver.cpp", line 89: cc0286: error: base class "Plugin" is 
     ambiguous 
if (!m_pMgr->RegisterPlugin(this)) 

방법이 포인터 모호하고, 어떻게 그것을 해결하는 방법은 무엇입니까?

감사합니다,

- 폴

답변

4

당신이 Driver에서 파생하는 경우, 당신은 명시 적으로 Driver의 기지의 생성자를 호출 할 필요가 없습니다 :

class NewDriver : public Driver { /* ... */ }; 
NewDriver::NewDriver() : Driver() {} 

다음 Driver의 생성자 자신의 기지를 초기화 할 필요가 없으며 그렇게해서는 안됩니다. 이 다르게 동작해야하는 경우
,이 매개 변수를 보자 :

class Driver : /* ... */ { 
public: 
    Driver(const std::string& name /* , ... */) 
     : CmdObject(name /* , ... */) 
    {} 
    // ... 
}; 

NewDriver::NewDriver() : Driver("NewDriver" /* , ... */) {} 
+3

엄밀히 말하면 기본 클래스 ctor가 매개 변수를 사용하지 않으면 해당 매개 변수를 입력하지 않아도됩니다. 초기화 목록은 자동으로 기본값으로 생성되므로 –

+0

@dash, 그건 완전히 정확하지 않습니다 (적어도 g ++에서는 그렇지 않습니다). 사실 상속 된 유형은 가상 상속되지 않은 유형보다 먼저 초기화됩니다. 따라서 초기화 순서가 실제 상속 계층과 물리적 인 상속 계층 사이에서 다른 경우 일부 컴파일러는 초기화 목록을 생략하고 컴파일러가 다음을 수행 할 수 있도록 초기화 순서에 대한 경고를 표시하기 시작합니다. 주문 자체를하십시오). –

+0

나는 간단하게 말씨를 바꿨다. 나는 여기서 가능한 다른 모든 복잡함에 들어가기를 원치 않는다. –

0

나는 가상 상속을 도입하는 것은 당신이 가고 싶은 방법입니다 확실하지 않다. 당신이 얻은 초기 오류는 유효합니다 - 당신은 CmdObject() ctor를 Driver 클래스의 '위'에서 호출하려고합니다. Driver 클래스에 다른 ctor를 추가 할 수 있습니까?

1

게오르그에는 정확한 답이 있습니다.이 경우 다중 상속이 필요하지 않습니다. 특히 dreaded diamond을 만들려면 multiple inheritance를 사용

낙담 강하게이며, C++ 프로그래머의 대다수 혼란과 좌절의 많은으로 이어질 것입니다.

0

이러한 클래스에서 다시 상속 받기를 원하는 이유가 있다면 가상 상속을 사용하지 않아야합니다. 가상 상속을 사용하려면 더 많은 기본 클래스에서이를 지정해야합니다. 그러나 가상 상속을 여기에서 사용하고 싶지는 않습니다. Driver가 이미 그렇게하고 있기 때문에 기본 클래스의 initializer를 생략하십시오.예를 들어, NewDriver 생성자는 전혀 필요하지 않습니다. 구현에 실제로 필요하다면, 만 NewDriver의 멤버 변수를 초기화하는 데 사용해야하며 Driver가 올바른 작업을 수행해야합니다. Driver가 올바른 일을하지 않는다면, 적절한 매개 변수를 취하는 생성자를 제공하고 해당 생성자가 올바른 작업을 수행하도록하십시오. 예 :

class Driver : public Stuff 
{ 
public: 
    Driver(const char* enginename) : Stuff(99), m_Engine(enginename) { } 

private: 
    Engine m_Engine; 
}; 

class NewDriver : public Driver 
{ 
public: 
    NewDriver() : Driver("New Driver!") { } // yes, Stuff gets initialized with 99 automatically! 
}; 
0

CmdObjectDriver 내에서 충분합니다. 지정된 제한 내에서 CmdObject을 사용자 정의 할 수있는 protected 생성자를 갖도록 Driver을 조정하십시오.

class Driver ... 
protected: 
    Driver(std::string driverName, std::string engineName); 

...

Driver::Driver(std::string driverName, std::string engineName) : 
    YCmdObject(driverName, (CmdObjectType)100, true), 
    m_Engine(engineName) { 

...

NewDriver::NewDriver() : 
    Driver("NewDriver", "MyNewEngine") { 
    ... 
} 
1

당신은 계층 구조를 작성하는 경우 :

class A {public: a(int i){} }; 
class B : public A {public: b(){} }; 
class C : public B {public: c(); }; 

당신은 A의 생성자에 인수를 전달할 수 없습니다를 직접 C 년대가 형성 생성자

C::C() : A(5) {} // illegal 

A는 특별한 경우이며,이 경우에 유용 B의 가상 기본 클래스가 아닌. Tim Sylvester가 제공하는 링크를 확인하십시오.

컴파일러에서이 사례를 언급했다고해서 그것이 당신을위한 해결책이라는 것을 의미하지는 않습니다.

귀하의 코드와 같은 계층 구조를 만들 경우 NewDriver 개체에 유형의 하위 개체 2 개와 CmdObject 유형 2 하위 개체가 있습니다. 이 경우 NewDriver* 유형의 포인터를 Plugin* 유형으로 다운 캐스팅하려고하면 컴파일러는 NewDriver 개체에있는 2 개의 하위 개체 중 어느 개체에 있는지 알지 못하기 때문에 주소를 조정하는 방법을 알지 못합니다 그 포인터는 가리 키도록되어 있습니다. 그것이 오류 메시지에 언급 된 모호성이 어디서 오는가입니다. 컴파일러에게 알려줄 수있는 방법이 있지만, 내가 설명하고있는 혼란은 이미 그렇게하지 않았다는 것을 당신에게 확신시켜야한다고 생각합니다.

1

다중 상속의 황금률 - ALL 클래스 MUST모든 대중 기지가 가상합니다. 해당 규칙을 따르는 한 다중 상속이 제대로 작동합니다. 귀하의 경우에는 Plugin이 선언되지 않았기 때문에 모호한 기본 클래스 오류가 발생합니다.