2009-12-12 6 views
2

가상 기능 문제로 친구에게 질문을 받았습니다.C++ 가상 함수에 대한 하나의 질문

자식 개체가 어떤 조건에서 가상 함수를 호출하면이 가상 함수는 실제로 아버지 구현에서 실행됩니다.

+3

는 ++, 용어 "기본 클래스"를 사용) 할 때를 "아이"라고 할 때 "아버지"와 "파생 된 클래스"라고 말하십시오. –

+0

"이 가상 함수가 실제로 아버지의 구현에서 실행 된 것"은 무엇입니까? 자식 구현은 부모 구현을 실행합니까? 또는 부모 구현이 직접 실행되고 자식 구현이 전혀 실행되지 않습니까? – AnT

답변

0

자식 클래스의 소멸자가 이미 호출 된 경우 개체의 부모 유형이므로 개체의 가상 함수가 호출됩니다.

+1

C++ 표준은 확실히 그러한 것을 말하지 않습니다. –

+0

안녕하세요, 예를 들어 줄 수 있습니까? 안녕하세요 닐 이 질문에 대한 답변은 무엇입니까? – skydoor

+0

표준을 인용 할 수는 없지만 http://c2.com/cgi/wiki?PureVirtualFunctionCalled 및 http://msdn.microsoft.com/ko-us/magazine/cc163897을 작성하지 않았습니다. aspx –

3

당신이 무엇을 요구하고 있는지 명확히하기 위해 코드를 게시 할 필요가 있다고 생각합니다. 그러나 소멸자를 제외하고는 자식이 자신의 함수에서 명시 적으로 itt를 호출하지 않으면 기본 클래스 함수가 ​​호출되지 않습니다. 예를 들어,

struct A { 
    virtual ~A() {} 
    virtual void f() {} 
}; 

struct B : public A { 
    virtual void f() {} 
}; 

int main() { 
    A * a = new B; 
    a->f(); 
    delete a; 
} 

B의 가상 함수 f() 만 호출됩니다. 당신이 호출 할 수있는 :: f를()를 원한다면 그렇게 명시 적으로해야 할 것 :

struct B : public A { 
    virtual f() { 
     A::f(); // explicit call 
    } 
}; 
B는 함수를 선언하지 않습니다 아, 그리고 경우에 물론

-이 경우에는 :: F()가 항상 호출됩니다.

+0

아직 코드가 없습니다.나는 질문이 클래스 B처럼 생각 { 가상 F() {cout을 << << endl의 "자료";} } 클래스 D { 가상 F() {cout과 << " in derived "<< endl;} } 두 개의 객체 d와 b가 있는데, d가 df() 함수를 호출하면"in Base! "가 표시됩니다. 어떤 상황에서 이런 일이 발생합니까? – skydoor

+1

가상 호출은 객체 인스턴스를 통하지 않고 포인터와 참조를 통해서만 발생합니다. –

+0

글쎄, 귀하의 의견에 감사드립니다. 그러나 나는 약간의 오해가 있다고 생각한다. 질문은 파생 된 객체가 가상 함수를 호출하는 이유이지만 기본 클래스의 함수가 실행되는 것입니다. 기본 클래스에서 함수를 호출하는 방법이 아닙니다. – skydoor

0

이 호출이 생성자를 사용하는 경우 디스패치는 정적입니다. 이 가상이라는 사실에도 불구하고 :: f를이

struct A { 
    A() { f(); } 
    virtual void f() { } 
}; 

struct B : A { 
     B() :member(0) {} 
     void f() { std::cout << member; } 
    private: 
     int member; 
}; 

int main() { 
    B b; 
    return 0; 
} 

호출 된 F와 호출 : 여기

http://cplusplus.co.il/2009/09/30/virtual-dispatching-within-a-constructor-or-a-destructor/ 내가 링크 한 기사에서 예제 : 자세한 정보를 원하시면이 읽기 B 자체의 구현을 가지는 B 형의 객체

+0

이것과 네드의 답변은 정적 인 디스패치와 관련이 있습니다. 나는 OP가 가상 파견에 관해 생각하고 있다고 생각한다. 그의 답변에 대한 그의 코멘트는 그것을 나타내는 것처럼 보인다. –

+1

dispath가 * static *이라고 말하는 것은 잘못되었습니다. 파견은 정적이지 않습니다. 가상 함수의 언어 관점에서 파견은 ​​항상 * 동적 *이지만, 생성자로부터 호출이 생성 될 때 객체의 동적 유형은 생성자가 현재 작업중인 클래스입니다. 정적 배설 *의이 이상한 생각이 어디서 왔는지 나는 모른다. 컴파일러는 정적이되도록 최적화 할 수 있지만 컴파일러 만의 최적화입니다. – AnT

+0

그래서 (예제 코드를 사용하여) A a; a.f(); 이게 역동적 인 파견 이라구요? –

2

현재 형식의 질문에 정확히 무엇이 내포되어 있는지 이해하는 것은 불가능합니다.

문자 그대로하면, 문제는 분명하고 즉각적인 대답을 가지고 : 부모의 구현은 해당 기능에 대한 최종 overrider 아이가 자신의

class parent { 
public: 
    virtual void foo() { /* whatever */ } 
}; 

class child : parent { 
public: 
    void bar() { 
    foo(); /* call the parent's implementation, as requested */ 
    } 
}; 
의 어떤 구현을 제공하지 않습니다 즉 경우, 경우 부모의 버전이라고합니다

그래서 여기에 답이 있습니다.

당연히 그 질문에 내포 된 것이 아니라는 것이 누구에게나 직관적으로 명백합니다. 아마도 하위 클래스가 부모 함수를 재정의한다는 암시가있을 수 있습니다. 이 경우 다른 명백한 답이있다 : 부모의 버전이 호출 될 아이가 함수의 정규화 된 이름을 사용하는 경우

class parent { 
public: 
    virtual void foo() { /* whatever */ } 
}; 

class child : parent { 
public: 
    virtual void foo() { /* whatever */ } 
    void bar() { 
    parent::foo(); /* call the parent's implementation, as requested */ 
    } 
}; 

또 다른 가능한 대답은 함수가 실제로 호출되는 객체가 parent 유형을 가지고 있다는 것입니다

class parent { 
public: 
    virtual void foo() { /* whatever */ } 
}; 

class child : parent { 
public: 
    virtual void foo() { /* whatever */ } 
    void bar() { 
    parent p; 
    p.foo(); /* call the parent's implementation, as requested */ 
    } 
}; 

다시,이 질문에 대해하지 어떤 것을 직관적으로 느끼는 (아무데도 문제가 있기 때문에 그것은 아이가 this 객체에 대해 호출해야한다고 말한다). 대부분의 경우, 문제는 가상 생성자로 만든 통화 및 소멸자 문제는 잘못 나가셨된다위한 그러나

class parent { 
public: 
    parent() { 
    foo(); /* always calls `parent::foo` */ 
    } 
    virtual void foo() { /* whatever */ } 
}; 

class child : parent { 
public: 
    child() : parent() /* `parent::parent` will call `parent::foo` */ 
    {} 
    virtual void foo() { /* whatever */ } 
}; 

에 대해 의도되었다. 호출의 마지막 예제에서 자식 객체는 아직 존재하지 않습니다.그것의 메모리는 이미 할당되었지만 수명은 아직 시작되지 않았습니다. 가상 함수에 대한 호출이 자식 객체에 의해 수행된다고 말하는 것은 잘못된 것입니다. 상위 오브젝트가 수행합니다.

위의 내용을 재개하려면 다음과 같이 질문하십시오. 모호하고 모호하게 말하면서 현재의 형태로는 의미가 없습니다. 파생하기 때문에 (파생 된 객체의 생성자가 아직 입력되지 않았기 때문에) 기본 클래스의 범위가 명시 적으로 기본 클래스의 생성자 내부 (Base::f();)

  • 사용

  • 1
    • 기본 클래스의 소멸자 내부
    • (

      것은 또한 수 있습니다 : 개체가 이미이 건축 중에 발생할 수 있습니다,

    0

    답변 이미 제공되었습니다) 파괴 된 런타임 오류의 재미 소스, 그래서는 기본 클래스에서 호출 생성자에 & 순수 가상 메소드를 특별한주의를 지불;

    http://support.microsoft.com/kb/125749 C에서

    class A; 
    
        void fcn(A*); 
    
        class A 
        { 
        public: 
         virtual void f() = 0; 
         A() { fcn(this); } 
        }; 
    
        class B : A 
        { 
         void f() { } 
        }; 
    
        void fcn(A* p) 
        { 
         p->f(); 
        } 
    
        // The declaration below invokes class B's constructor, which 
        // first calls class A's constructor, which calls fcn. Then 
        // fcn calls A::f, which is a pure virtual function, and 
        // this causes the run-time error. B has not been constructed 
        // at this point, so the B::f cannot be called. You would not 
        // want it to be called because it could depend on something 
        // in B that has not been initialized yet. 
    
        B b; 
    
        void main() 
        { 
        } 
    
    관련 문제