2013-05-07 2 views
0
#ifndef TEST_H 
#define TEST_H 
#include <iostream> 
#include <string> 
class A{ 
public: 
    virtual void test1() = 0; 
    virtual std::string test2() = 0; 
}; 

class B : public A{ 

public: 
    void test1(){ 
     std::cout << A::test2() << " World"; 
    } 
}; 
class C : public B{ 
public: 
    std::string test2(){ 
     return "hello"; 
    } 
}; 
class C1 : public B{ 
public: 
    std::string test2(){ 
     return "Sup"; 
    } 
}; 

#endif // TEST_H 

순수 가상 메서드 만있는 인터페이스 A가 있습니다. 나는 test1을 구현하고 test1을 구현하기 위해 test2을 사용하고자하는 추상 클래스를 가지고있다.추상 클래스에서 순수 가상 메서드 사용

이제 C와 C1 및 test2

을 구현하지만

error: cannot call member function 'virtual std::string A::test2()' without object

어떻게 C에서 이런 일을 할 것이다 클래스 B에 std::cout << A::test2() << " World";을 할 수없는 내 구체적인 클래스 ++?

+1

'A'와 'B'는 전혀 관련이 없습니다.그래서 당신은 그렇게 할 수 없습니다. 이 작업을 수행하려면'B'가'A'를 상속 받아야합니다. 당신의 디자인에 어떻게 어울리는 지 확신 할 수 없습니다. –

+0

클래스가'A'의 인터페이스를 구현하기 위해서는'A'에서 실제로 _inherit_해야합니다. –

+0

예. 미안 해요. –

답변

3

순수 가상 대 가상에 매달리지 마십시오. A에 선언 된 두 함수는 모두 가상 함수이므로 해당 함수 만 처리 할 수 ​​있습니다. 그래서 Btest1 구현은 test2을 호출해야합니다. 아니요 A:: 한정자. 그러면 가상 전화가 걸리고 가장 유래 한 test2 버전, 즉 C 또는 C1에 정의 된 버전으로 개체 유형에 따라 달라집니다. 내가 A::test2()에서 A::을 제거 한 후, 다음 코드는 (예상대로) 작동 :

int main() { 
    C c; 
    c.test1(); 
    C1 c1; 
    c1.test1(); 
    return 0; 
} 

[work]$ g++ test.cpp 
[work]$ ./a.out 
hello WorldSup World[work]$ 

예, 당신은 출력에 \n을 추가해야합니다.

2

class Bclass A에서 상속해야합니다. 그것은 시체가 없습니다 - 클래스가 구현되지 않기 때문에, 작동하지 않습니다 A::test2()를 호출 물론

class B: public A ... 

. 다음과 같이 클래스 A에 구현하면 해결할 수 있습니다.

std::string A::test2() { return "some string"; } 
+0

그것이 인라인 순수 가상 함수로되어 있습니까? 인라인 순수 가상 함수는 표준에서 허용되지 않습니다. 클래스 본문 밖에서 정의해야합니다. –

+0

정말요? 필자는 "순수 가상 구현"을 사용한 적이 없지만 사용자가 인라인 할 수 있다고 생각했습니다. 그러나 나는 그것을 편집 할 것이다. –

+0

나는 지금 당황하고있다. 내가해야 할 일을 더 분명히 해줄 수 있니? –

2

가상 전화를 원할 경우 명시 적 범위 자격을 사용하지 마십시오. A::test2을 사용하면 A::test2을 동적 디스패치없이 호출하려고 시도합니다. A::test2에는 구현이 없으므로 차례로 연결이 끊어집니다.

+0

그래서 여러분이 말하는 것은 test2()를 호출하는 것입니다. 대신 A :: test2(); ? 나는 같은 결과를 얻는다. –

+0

실제로 이것을 시도 할 때 나는 완전히 다른 결과를 얻습니다. 특히 초기 코드는 컴파일되지만 링크가되지 않습니다 (링커는 A :: test2의 구현을 찾을 수 없다는 불평을합니다). A ::를 제거하면 올바르게 컴파일되고 실행됩니다. 그래서 당신은 매우 버그가 많은 컴파일러를 사용하고 있거나 사용중인 코드를 실제로 게시하지 않았습니다. 어딘가에서 길잃은'정적'을 가지고 있습니까? –

+0

오케이 와우 흠. 나는 약간의 오류를 던지는 GCC 4.8을 사용했다. 그러나 그것은 clang에서 잘 컴파일됩니다. –

2

오류 메시지 <g> 당신이 그것을 컴파일 할 때, BA에서 상속하지 않았기 때문에에 멤버 함수를 호출하는 형태 A의 어떤 객체가 없다는 것을 의미한다. 게시 한 코드에서 다른 오류가 발생합니다 : A::test2이 정의되지 않았습니다.

거의 확실하게 함수를 가상으로 호출해야합니다 (예 : C 또는 C1 또는 기타로 호출). 이 경우 전혀 필요하지 않은 :

std::cout << test2() << std::endl; 

코드는 특히 오히려 어떤 재정보다 버전이 A 선언 전화를 시도합니다. 즉 (I 의심하는) 당신이 원하는 것을 실제로 있다면, 그 함수가 정의 될 필요가있을 것이다 : 인해 언어의 특질에,

std::string A::test2() { 
    return "I'm a pure virtual function. Why are you calling me?"; 
} 

하는 것으로, 순수 가상 함수는 클래스 내에서 정의 할 수 없습니다 정의; 이 정의는 수업을 벗어나야합니다.

관련 문제