순수 가상 함수에는 인라인 정의가 없을 수 있습니다. 왜?
순수 가상 함수는 가상이고 순수 지정자 ( = 0;
) 가있는 멤버 함수입니다.
C ++ 03의 10.4 절 2 절 은 추상 클래스가 무엇인지, 그리고 부수적으로 다음을 알려줍니다.
[참고 : 함수 선언은 순수 지정자와 정의를 모두 제공 할 수 없습니다. — 엔드 노트] [예 :
struct C {
virtual void f() = 0 { }; // ill-formed
};
-예제 끝]
이 문제에 익숙하지 않은 사람들을 위해 순수 가상 함수는 정의를 가질 수 있지만 위에서 언급 한 절은 이러한 정의가 인라인으로 표시되는 것을 금지합니다 (어휘 적으로 클래스에 있음). (순수한 가상 함수를 정의하는 데 사용하는 경우 예를 들어이 GotW )
이제 다른 모든 종류와 유형의 함수에 대해 클래스 내 정의를 제공 할 수 있으며이 제한은 언뜻보기에 절대적으로 인위적이고 설명 할 수없는 것처럼 보입니다. 생각해 보면 두 번째와 그 이후의 눈에는 그런 것 같습니다. :)하지만 구체적인 이유가 없다면 제한이 없을 것이라고 생각합니다.
제 질문은 : 그 구체적인 이유를 아는 사람이 있습니까? 좋은 추측도 환영합니다.
메모:
- MSVC에서는 PVF가 인라인 정의를 가질 수 있습니다. 그러니 놀라지 마세요 :)
inline
이 질문 의 단어 는 인라인 키워드를 의미하지 않습니다 . 뜻한다 동급 어휘
SO 스레드에서 "왜 순수 가상 함수가 0으로 초기화됩니까?" Jerry Coffin은 Bjarne Stroustrup의 The Design & Evolution of C ++ , 섹션 §13.2.3 에서이 인용문을 제공 했으며 여기에서 관련성이 있다고 생각하는 부분을 강조했습니다.
=0
새로운 키워드 순수 또는 추상을 도입하는 명백한 대안보다 흥미로운 구문이 선택되었습니다. 그 당시에는 새 키워드를 받아 들일 기회가 없었기 때문입니다. 순수하다고 제안했다면 릴리스 2.0은 추상 클래스없이 제공되었을 것입니다. 더 좋은 구문과 추상 클래스 중 하나를 선택했기 때문에 추상 클래스를 선택했습니다. 지연을 감수하고 순수에 대한 특정 싸움을 유발하는 대신, 저는 0을 사용하여 "거기 없음"을 나타내는 전통 C 및 C ++ 규칙을 사용했습니다.=0
와 구문 맞는 기능 체 기능을위한 초기화 것이 내보기 또한 가상 함수 세트 (단순하지만, 일반적으로 적절한)보기 함수 포인터 벡터로서 함께 구현되고. […]
따라서 구문을 선택할 때 Bjarne은 함수 본문을 선언자의 일종의 이니셜 라이저 부분으로 생각하고 =0
있으며, "본문 없음"(또는 그의 말로 "없음")을 나타내는 다른 형식의 이니셜 라이저로 생각했습니다.
개념적 그림에서 "거기"와 신체를 둘 다 가질 수 없다는 것은 당연합니다.
또는 여전히 개념적 그림에서 두 개의 이니셜 라이저가 있습니다.
자, 그것은 나의 텔레파시 능력 인 google-foo와 soft-reasoning이가는 한입니다. 이 순전히 구문 적 제한을 해제하고 그에 수반되는 모든 작업을 추적하는 것에 대한 제안을위원회에 공식화하는 데 관심이 충분한 사람은 아무도 없다고 생각합니다. 따라서 여전히 그 방법입니다.
표준화위원회에 대한 믿음이별로 없어야합니다. 모든 것이 그것을 설명 할 깊은 이유가있는 것은 아닙니다. 어떤 것은 처음에는 아무도 다르게 생각하지 않았고 아무도 그것을 바꾸는 것이 충분히 중요하다고 생각하지 않았기 때문에 그렇게됩니다. 충분히 오래된 것들은 첫 번째 구현의 아티팩트 일 수도 있습니다. 일부는 진화의 결과입니다. 한 번에 깊은 이유가 있었지만 이유가 제거되었고 초기 결정이 다시 고려되지 않았습니다 (여기서도 초기 결정이 순수한 기능은 금지되었습니다). 일부는 서로 다른 POV 간의 협상 결과이며 결과에는 일관성이 없지만 합의에 도달하는 데 필요한 것으로 간주되었습니다.
좋은 추측 ... 음, 상황을 고려하면 :
- 함수를 인라인으로 선언하고 명시 적으로 인라인 본문 (클래스 외부)을 제공하는 것이 합법적이므로 클래스 내부에서 선언되는 유일한 실제 의미에 대해 이의가 없습니다.
- 문법에 잠재적 인 모호함이나 충돌이 도입되지 않았으므로 현장에서 함수 정의 를 제외 할 논리적 이유가 없습니다 .
내 생각 엔 순수 가상 함수에 대한 본문의 사용은 = 0 | { ... }
문법이 공식화 된 후에 실현되었으며 문법은 단순히 수정되지 않았습니다. 더 논리적이고 일관되게 만드는 것을 포함하여 언어 변경 / 향상을위한 많은 제안이 있다는 것을 고려할 가치가 있지만 누군가가 선택하고 공식 제안으로 작성되는 숫자는 훨씬 적고 숫자는 훨씬 적습니다. 위원회가 고려할 시간이 있고 컴파일러 공급 업체가 구현할 준비가되어 있다고 생각하는 항목 중 다시 한 번 더 작습니다. 이와 같은 일에는 챔피언이 필요하며 아마도 당신은 그 문제를 처음으로 본 사람 일 것입니다. 이 프로세스에 대해 알아 보려면 http://www2.research.att.com/~bs/evol-issues.html을 확인 하세요 .
좋은 추측은 환영합니다.
나는 생각 = 0
상기 선언이 마음에 구현 데에서 비롯됩니다. 대부분의 경우이 정의 는 클래스 정보 NULL
의 RTTI 항목 ( vtbl
런타임 에 클래스 멤버 함수 의 주소 가 저장 되는 위치) 을 가져 오는 것을 의미 합니다 .
그러나 실제로 파일에 함수 정의 를 넣을 때 링커의 개체 파일에 이름 을 *.cpp
도입 합니다. 특정 함수를 찾을 파일 의 주소입니다 .*.o
그러면 기본 링커는 더 이상 C ++에 대해 알아야합니다. 으로 선언 했더라도 함께 연결할 수 있습니다 = 0
.
나는 행동을 잊었음에도 불구하고 당신이 묘사 한 것이 가능하다고 읽었다 고 생각합니다 :-) ...
소멸자를 제쳐두고 순수 가상 함수의 구현은 자연스러운 방식으로 호출되지 않기 때문에 이상한 일입니다. 즉, Base 클래스에 대한 포인터 또는 참조가있는 경우 기본 객체는 항상 함수를 재정의하는 Derived이며 항상 호출됩니다.
실제로 호출 할 구현을 가져 오는 유일한 방법은 파생 클래스의 오버로드 중 하나에서 Base :: func () 구문을 사용하는 것입니다.
이것은 실제로 어떤면에서 컴파일러가 호출하려는 지점에서 호출되는 오버로드가 항상 명확하므로 인라인을위한 더 나은 대상이됩니다.
또한 순수 가상 함수에 대한 구현이 금지 된 경우 파생 된 함수에서 정기적으로 호출 할 수있는 Base 클래스의 다른 (아마 보호되는) 비가 상 함수에 대한 명백한 해결 방법이 있습니다. 물론 범위는 모든 함수에서 호출 할 수 있다는 점에서 덜 제한됩니다.
(그런데 나는 Base::f()
from이 Derived::f()
아닌 이 구문으로 만 호출 할 수 있다는 가정하에 있습니다 Derived::anyOtherFunc()
.이 가정에 맞습니까?).
순수 가상 소멸자는 어떤 의미에서 다른 이야기입니다. 다른 곳에 순수한 가상 함수가없는 누군가가 파생 클래스의 인스턴스를 만드는 것을 방지하기위한 기술로 사용됩니다.
"왜"허용되지 않는지에 대한 실제 질문에 대한 대답은 실제로는 표준위원회가 그렇게 말했기 때문입니다. 그러나 제 대답은 우리가 어쨌든 달성하고자하는 것에 대해 약간의 빛을 비 춥니 다.
'developer tip' 카테고리의 다른 글
Win32에서 힙 손상; (0) | 2020.12.09 |
---|---|
ggplot2에서 범례를 이동하거나 배치하는 방법 (0) | 2020.12.09 |
int에서 해제 / nullable 변환이있는 심각한 버그, 십진수 변환 허용 (0) | 2020.12.09 |
분기없는 K- 평균 (또는 기타 최적화) (0) | 2020.12.09 |
React Router 인증 (0) | 2020.12.09 |