2011-01-24 2 views
2

추상 클래스가있는 곳에서 메소드 오버라이드를 올바르게 처리하는 데 문제가 있습니다. 내 클래스 계층 구조 내에 이 있습니다. 내가 설명하려고합니다 :추상 클래스의 C++ 및 상속

class AbstractClass{ 
public: 
    virtual void anyMethod() = 0; 
}; 

class A : public AbstractClass { 
    void anyMethod() { 
     // A implementation of anyMethod 
     cout << "A"; 
    } 
}; 

class B : public AbstractClass { 
    void anyMethod() { 
     // B implementation of anyMethod 
     cout << "B"; 
    } 
}; 

AbstractClass *ptrA, *ptrB; 

ptrA = new A(); 
ptrB = new B(); 
ptrA->anyMethod(); //prints A 
ptrB->anyMethod(); //prints B 

Ok..previous 예를 잘 작동이 있습니다 .. AbstractClass 방법 anyMethod의 구체적인 구현은 런타임에 호출됩니다. 그러나 AbstractClass는 anyMethod라는 가상이 아닌 방법이 다른 기본 클래스에서 파생 : 나는 무엇을 오해하고

ptrA = new A(); 
ptrB = new B(); 
ptrA->anyMethod(); //prints OtherClass 
ptrB->anyMethod(); //prints OtherClass 

: 내가 그런 일을하려고하면, 지금

class OtherClass { 
public: 
    void anyMethod() { 
     cout << "OtherClass"; 
    } 
}; 

class AbstractClass : public OtherClass { 
public: 
    virtual void anyMethod() = 0; 
}; 

//A and B declared the same way as described before. 

를? cast, typeid 등을 사용하지 않고 ptrA 및 ptrB A 및 B를 인쇄하기위한 솔루션이 있습니까?

+0

코드를 형식화하십시오. – Elalfer

+3

A와 B는 두 번째 경우에도 인쇄해야합니다. 당신의 설명에서 뭔가 빠졌습니까? – vitaut

+3

g ++에서 코드를 테스트하고 두 경우 모두 A와 B를 인쇄합니다. 혹시'OtherClass * '를 사용하고 있습니까? – casablanca

답변

0

답해 주셔서 감사합니다. 문제를 이해하는 데 많은 도움을주었습니다. 실제로 잘못된 문제를 게시했습니다. 실제 문제를 오해하고 있었기 때문입니다. 어쨌든, 나는 내 문제를 부분적으로 해결했다고 생각합니다.

#include <iostream> 

`` using namespace std; 

class Other{ 

public: 

void foo(){ 
     cout << "Other\n"; 
} 

void foo(int a){} 
}; 

class Abstract : public Other{ 

public: 
virtual void foo() {}; 
virtual void foo(int c){ 
     Other::foo(c); 
} 
}; 

class A : public Abstract{ 

public: 

void foo(){ 
     cout << "A\n"; 
} 
}; 

class B : public Abstract{ 

public: 

void foo(){ 
     cout << "B\n"; 
} 
}; 
int main(){ 

cout << "main\n"; 

Abstract * ptrA = new A(); 
Abstract * ptrB = new B(); 

Other *o = new Other(); 
o->foo(); 

ptrA->foo(); 
ptrB->foo(); 
ptrB->foo(3); //can't no more use the method foo with different signatures implemented in the base class Other, unless I explicitly redefined in the class Abstract 
dynamic_cast<Other*>(ptrB)->foo(3);//can't dynamic_cast from derived to base 

내가 두 가지 오류 만들고 있었다 : 다음은 코드의 내 실제 코드에서

  1. 을 (하지 전에 게시 된 단순화 된 버전) 내가 가상 에게 foo 함수를 선언하는 것을 잊었다()

  2. 가상 선언으로도 충분하지 않았습니다. 사실 그 함수의 모든 구현은 Abstract 클래스 내부에 래핑되어 서브 클래스 A 및 B에서 볼 수있게해야합니다. 그렇지 않으면 컴파일하지 않을 것이다.

깨끗한 해결책이 될 수 있는지 알 수 없습니다. 사실 모든 foo 메소드 서명을 포장해야합니다.

2

포인터 또는 참조가있는 기본 클래스에서 anyMethod이 가상으로 선언 된 경우 을 가상으로 검색하여 A 및 B를 올바르게 인쇄해야합니다. 그렇지 않다면, 당신이 할 수있는 것은 아무것도 없습니다 (가상으로 변경하는 것 이상).

5

왜하지 않는다 :

class OtherClass 
{ 
    public: 
    virtual void anyMethod() 
    { 
     cout << "OtherClass"; 
    }; 
} 

문제 해결해야

2

내가 생각하는 당신이 AB에서 오버라이드 (override) 할 OtherClass의 방법은 다음, 가상이 아닌 경우 오버라이드는 암시 적이 지 않습니다.

나는 명시 적으로 함수를 재정의하는 방법이 있다고 생각한다.

1

DeadMGs 답변은 물론 정확합니다.

이 포인터 ptrA과 낮은 예를 입력 OtherClassptrB 또는 AbstractClass 위치 : 당신이 OtherClass 메도를 변경할 수없는 경우에, 당신이 시도 할 수 있습니다 (예를 들어, 그것은 제 3 자 lib 디렉토리에서의)?

만약 그들이 OtherClass이라면 나는 당신이 묘사 한 행동을 기대합니다. 지금까지 내가 코드 OtherClass::anyMethod()에서 볼 수

dynamic_cast<AbstractClass*>(ptrA)->anyMethod();

+0

정확히 .. OtherClass는 서명을 수정할 수없는 타사 라이브러리에 있습니다. 나는 AbstractClass에서 virtual anyFunction을 선언하기 위해 실종되었다 (미안하지만 내가 게시 한 것은 내 코드의 매우 단순화 된 버전 임). 지금은 그 솔루션을 tryed하지만 문제는 OtherClass anyFunction에 여러 개의 다른 서명이 있다는 것입니다. 만약 내가 AbstractClass에서 모든 것을 다시 선언하지 않으면 약간의 충돌을 일으키는 것 같습니다. 몇 가지 테스트를하고 나중에 자세한 질문을 게시 할 것입니다. 모두에게 감사드립니다. – Heisenbug

1

을 가상하고 이미 구현되지 않습니다 : 그런 다음 AbstractClass 포인터를 캐스팅 시도 할 수 있습니다. virtual

0

두 번째 경우의 선언은 다음과 같다고 생각합니다. OtherClass * ptrA; AbstractClass * ptrA가 아니라; 첫 번째 경우처럼 선언하면 메서드가 가상이기 때문에 아무 문제가 없습니다. 그러나 OtherClass로 선언하면 컴파일러는 가상을 찾지 않고 vtble을 사용하지 않고이 메서드의 주소에 바인딩합니다.