가상 함수의 구현에 대해 많이 이야기한다고 생각합니다. 제 질문은 순수 가상 기능은 무엇입니까? 그러나 그것은 구현됩니까? 가상 테이블에서 순수 또는 비 순수이라고 말하는 법? 순수 가상 함수와 구현 가상 함수의 차이점은 무엇입니까?C++에서 순수 가상 함수를 구현하는 방법
답변
일반적으로 순수 가상 기능과 비 순수 가상 기능 간의 구현에는 차이가 없습니다. 순수 가상 함수가 정의되면 다른 가상 함수처럼 작동합니다. 정의되어 있지 않으면 명시 적으로 호출 된 경우에만 문제가 발생합니다.
동작에는 크게 두 가지 차이점이 있지만 일반적으로 가상 기능 메커니즘 자체의 구현에는 영향을주지 않습니다. 컴파일러는 상속 계층 구조에서 비 순수 최종 재 지정을 가지지 않는 순수 가상 함수를 가진 유형의 객체를 생성하도록 허용해서는 안되며 순수 가상 함수에 대한 가상 호출을 직접 또는 간접적으로 객체의 생성자 또는 소멸자는 정의되지 않은 동작을 발생시킵니다.
가상으로 호출되는 경우 정의되지 않은 동작입니다. 함수가 구현되어 있으면'AbstractBase :: Foo()'형식으로 호출 할 수 있습니다. –
정의되지 않은 경우 명시 적으로 호출하려고하면 링커 오류가 발생하는 경향이 있습니까? -하지만 추상 형식의 인스턴스를 가질 수 없다면 어떻게 사실상 호출 할 수 있습니까? – UncleBens
@UncleBens : 잘 모르겠다. 나는 표준의 10.4 부분을 그냥 의치 챘다. –
실제 구현은 잘 모르지만 vtable
에 NULL
포인터로 구현하는 것이 좋습니다. 즉, 구현이있는 경우 vtable
에 유효한 함수 포인터가 있고 순수 가상 인 경우 NULL
포인터가 있습니다.
이것은 매우 논리적이므로 나는 이이라고 생각합니다 .--).
가상 공백 foo() = 0;
순수 가상 함수는 여전히 가상 함수이므로 vtable에있을 수 있지만 컴파일러에는 구현이 필요하지 않으며 순수 가상을 선언하는 기본 클래스의 인스턴스화를 금지합니다. 추상 기본 클래스 유형의 포인터를 역 참조 할 수 있기 때문에 가상 테이블에는 다형성 및 런타임 바인딩을위한 항목이 있어야합니다.
도움이 되었습니까?
순수 가상 함수를 선언하면 vtable의 함수에 대한 항목이 추가됩니다. 순수 가상 함수 (및 재정의하지 않는 파생 클래스)를 선언하는 클래스에서 대부분의 구현은이 항목을 설정하여 일부 오류 메시지를 표시하는 일종의 진단 함수를 호출합니다 (예 : "오류 : 순수 가상 함수 호출 "). 순수 가상 함수를 정의 할 수는 있지만 사실상 호출 할 수는 없습니다. –
아, 맞습니다. 감사. 순수 가상 함수는 기본 클래스에 정의를 가질 수 있습니다. +1하여 수정하십시오. – codenheim
이 답이 아니라, A는 C++ 언어는 가상 파견 메커니즘이 건설 중에 일어나는 방법을 정의 this answer above
로 의견을 후속. 계층 구조에서 객체를 인스턴스화 할 때 기본 생성자가 호출됩니다 (*). 이 시점에서 가상 디스패치 메커니즘은 기본 클래스에 대해 초기화됩니다. 이 단계에서 가상 함수가 기본 구현에 전달됩니다. 가상 디스패치 메커니즘 (명시 적 클래스 자격없이)을 사용하는 비 순수 가상 메서드에 대한 호출은 기본 구현을 호출합니다. 베이스 생성자가 완료된 후
가상 송출기구 (일반적 VTABLE)는 유도 형 버전 reseted 얻는다 거기에서 동적 호출의 방법의 도출 버전 호출 :
struct base {
virtual void non_pure() { std::cout << "base::non_pure" << std::endl; }
virtual void pure_not_implemented() = 0;
virtual void pure_implemented() = 0;
base() { // at this point the object is a ´base´
non_pure(); // base::non_pure
// pure_not_implemented(); // runtime error: pure virtual method called
pure_implemented(); // base::pure_implemented
// base::pure_not_implemented(); // link error
}
};
void base::pure_implemented() { std::cout << "base::pure_implemented" << std::endl; }
struct derived : base {
virtual void non_pure() { std::cout << "derived::non_pure" << std::endl; }
virtual void pure_not_implemented() { std::cout << "derived::pure_not_implemented" << std::endl; }
virtual void pure_implemented() { std::cout << "derived::pure_implemented" << std::endl;
derived() { // after the implicit call to the base class
// this is a ´derived´ object, now calls will
// get dispatched to derived:: implementations
non_pure(); // derived::non_pure
pure_not_implemented(); // derived::pure_not_implemented
pure_implemented(); // derived::pure_implemented
base::non_pure(); // base::non_pure
// base::pure_not_implemented() // link error
}
};
을 동적 디스패치 메커니즘 (일반적으로 vtable)과 특정 메서드를 정규화 된 이름으로 호출하는 것 사이에는 차이점이 있습니다. 전체 자격을 통해 구현되지 않은 순수 가상 메서드에 대한 호출은 컴파일 타임에 허용되지만 링크시에는 실패합니다 (링커는 호출 할 구현을 찾을 수 없습니다).
이것은 언어 디자인에서 중요한 결정입니다. 다른 옵션 (자바가 취한)은 기본 클래스 생성자를 호출하기 전에 처음부터 가장 파생 된 유형으로 가상 디스패치 메커니즘을 초기화하는 것입니다.이 접근법의 문제점은 기본 생성자가 가상 메소드 (Java에서 모두 해당)를 호출하면 가장 파생 된 구현에 전달되어 아직 생성되지 않은 객체에서 실행되어 예상치 못한 결과가 발생할 수 있다는 것입니다.
public class Base
{
public Base() {
f();
}
public void f() {
System.out.println("Base.f");
}
}
public class Derived extends Base {
public final int constant;
public Derived() { constant = 5; }
public void f() {
System.out.println("Derived.f() " + constant);
}
public static void main(String args[]) {
Derived d = new Derived(); // prints Derived.f() 0
}
}
동적 버전 관리 메커니즘은 객체가 처음부터 Derived
유형으로 간주합니다. 기본 생성자에서 f()
에 대한 호출이 파생 된 구현에 동적으로 전달됩니다. 위의 예제에서 변수가 final로 선언되었으므로 값이 5 인 상수 (코드에서 명확하게 나타남) 인 경우에도 Derived
의 생성자가 실행되지 않았기 때문에 실제 인쇄 된 값은 0입니다.
(*) 이것은 지나치게 단순화되어 있지만 세부 사항은 실제로 인수에 영향을주지 않습니다.
생성자에서 순수 가상을 호출하는 것이 정의되지 않은 동작이되는 이유가 궁금했지만 순수하지 않은 호출은되지 않습니다. 특히, 컴파일러가 감지하기가 어렵습니까? 순수 함수를 호출하는 것이 (어떤 이유로 든) 바람직하지 않다면 대신 컴파일러 진단을 요구하지 않는 이유는 무엇입니까? – UncleBens
비 순수 가상 메소드 호출을 호출하면 현재 유형을 포함하여 대부분 파생 된 구현을 호출하지만 그 유형은 포함하지만 그 자손은 호출하지 않는 효과가 있습니다. 순수 가상 메서드 호출의 효과는 디스패치 메커니즘에 의존 할 수 있으므로 정의되지 않습니다. 대부분의 컴파일러는 합성 코드를 호출하여 현명한 메시지로 응용 프로그램을 진단하고 종료합니다. –
컴파일러가 생성자를 처리하는 시점에서 구현 된 순수 가상 메서드 (정의를 볼 수있는 경우)인지는 알 수 있지만 순수 가상 메서드가 다른 변환 단위로 구현되지 않을 수도 있습니다 (어쩌면). 생성자는 클래스 선언에 인라인되어 있고 순수 가상 메서드가 다른 번역 단위에 정의되어있는 동안 번역 단위에서 포함됩니다) –
- 1. 순수 가상 함수를 "삭제"하는 방법이 있습니까?
- 2. C에서 qsort를 구현하는 방법
- 3. 이것은 불순한 가상 함수를 구현하는 합법적 인 방법입니까?
- 4. 순수 가상 함수가
- 5. 인터페이스의 순수 가상 소멸자
- 6. 순수 가상 함수 호출
- 7. 순수 가상 메서드
- 8. C에서 간단한 파이썬 함수를 구현하는 것이 간단합니까?
- 9. 는 순수 가상 보호 특성을
- 10. Objective-C에서 C++ 순수 가상 함수와 동일한 기능은 무엇입니까?
- 11. 하스켈에서이 함수를 구현하는 방법
- 12. 별도의 상속 된 메서드를 '사용'하여 순수 가상 함수를 덮어 씁니다.
- 13. 가상 함수와 순수 가상 함수의 차이점은 무엇입니까?
- 14. 순수 가상 메서드없이 클래스 추상화하기
- 15. 순수 가상 소멸자에 대한 질문
- 16. C에서 사전을 구현하는 빠른 방법
- 17. C에서 거대한 행렬을 구현하는 방법
- 18. 리눅스에서 C의 타이머 콜백 함수를 구현하는 방법
- 19. 파생 클래스 내에서 개인 가상 함수를 구현하는 방법은 무엇입니까?
- 20. Objective-C에서 조각 별주기 함수를 구현하는 가장 좋은 방법은 무엇입니까?
- 21. C++의 순수 가상 함수 구현 및 헤더 파일
- 22. C++의 순수 가상 함수에 관한 질문?
- 23. 바디가있는 순수 가상 함수의 사용 사례는 무엇입니까?
- 24. C++ : 순수 가상 멤버 변수를 재정의 하시겠습니까?
- 25. C++ map.clear() 순수 가상 메서드 런타임 오류
- 26. 순수 가상 함수 및 추상 클래스
- 27. 순수 가상 함수는 어디에서 C++에 있습니까?
- 28. 완전히 순수 가상 클래스의 Vtable 배치
- 29. 템플릿을 사용하여 Combine 함수를 구현하는 방법
- 30. 기본 클래스에서 함수를 구현하는 일반적인 방법 찾기
http://stackoverflow.com/questions/2156634/why-pure-virtual-function-is-initialized-by-0 –