C ++ 가상 함수 반환 유형
상속 된 클래스가 다른 반환 유형으로 가상 함수를 구현할 수 있습니까 (템플릿을 반환으로 사용하지 않음)?
경우에 따라 예, 반환 유형이 원래 반환 유형과 공변 하는 경우 파생 클래스가 다른 반환 유형을 사용하여 가상 함수를 재정의하는 것이 합법적입니다 . 예를 들어 다음을 고려하십시오.
class Base {
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
};
class Derived: public Base {
public:
virtual Derived* clone() const {
return new Derived(*this);
}
};
여기에서 를 반환하는 Base
라는 순수 가상 함수를 정의 clone
합니다 Base *
. 파생 된 구현에서이 가상 함수는 반환 유형을 사용하여 재정의됩니다 Derived *
. 반환 유형은 기본과 동일하지 않지만 언제든지 작성할 수 있기 때문에 완벽하게 안전합니다.
Base* ptr = /* ... */
Base* clone = ptr->clone();
에 대한 호출 clone()
은 항상 Base
객체에 대한 포인터를 반환합니다.를 반환 Derived*
하더라도이 포인터는 암시 적으로 a로 변환 가능 Base*
하고 작업이 잘 정의되어 있기 때문입니다.
보다 일반적으로 함수의 반환 유형은 서명의 일부로 간주되지 않습니다. 반환 유형이 공변이면 모든 반환 유형으로 멤버 함수를 재정의 할 수 있습니다.
예. 반환 유형은 공변 인 한 다를 수 있습니다 . C ++ 표준은이를 다음과 같이 설명합니다 (§10.3 / 5).
재정의 함수의 반환 유형은 재정의 된 함수의 반환 유형과 동일하거나 함수 클래스와 공변 해야합니다. 함수가 함수를
D::f
재정의하는B::f
경우 다음 기준을 충족하는 경우 함수의 반환 유형은 공변입니다.
- 둘 다 클래스에 대한 포인터 또는 클래스 98에 대한 참조 )
- 의 반환 유형에
B::f
있는 클래스는D::f
또는 의 반환 유형에있는 클래스와 동일한 클래스이고,의 반환 유형에있는 클래스 의 명확한 직접 또는 간접 기본 클래스이고에서D::f
액세스 할 수 있습니다.D
- 포인터 또는 참조는 모두 동일한 cv-qualification을
D::f
가지며의 반환 유형에있는 클래스 유형은의 반환 유형에있는 클래스 유형과 같거나 더 적은 cv-qualification을 갖습니다B::f
.
각주 98은 "클래스에 대한 다중 레벨 포인터 또는 클래스에 대한 다중 레벨 포인터에 대한 참조는 허용되지 않습니다."라고 지적합니다.
요컨대, if D
가의 하위 유형 이면 B
의 함수 D
의 반환 유형은에서 함수의 반환 유형의 하위 유형이어야합니다 B
. 가장 일반적인 예는 반환 유형이 D
및을 기반으로 B
하지만 반드시 그럴 필요는없는 경우입니다. 두 개의 개별 유형 계층이있는 경우를 고려하십시오.
struct Base { /* ... */ };
struct Derived: public Base { /* ... */ };
struct B {
virtual Base* func() { return new Base; }
virtual ~B() { }
};
struct D: public B {
Derived* func() { return new Derived; }
};
int main() {
B* b = new D;
Base* base = b->func();
delete base;
delete b;
}
The reason this works is because any caller of func
is expecting a Base
pointer. Any Base
pointer will do. So, if D::func
promises to always return a Derived
pointer, then it will always satisfy the contract laid out by the ancestor class because any Derived
pointer can be implicitly converted to a Base
pointer. Thus, callers will always get what they expect.
In addition to allowing the return type to vary, some languages allow the parameter types of the overriding function to vary, too. When they do that, they usually need to be contravariant. That is, if B::f
accepts a Derived*
, then D::f
would be allowed to accept a Base*
. Descendants are allowed to be looser in what they'll accept, and stricter in what they return. C++ does not allow parameter-type contravariance. If you change the parameter types, C++ considers it a brand new function, so you start getting into overloading and hiding. For more on this topic, see Covariance and contravariance (computer science) in Wikipedia.
A derived class implementation of the virtual function can have a Covariant Return Type.
참고URL : https://stackoverflow.com/questions/4665117/c-virtual-function-return-type
'programing' 카테고리의 다른 글
위임이 아닌 STL 컨테이너에서 구현을 상속해도 괜찮습니까? (0) | 2020.10.24 |
---|---|
플롯 축의 눈금 간격을 변경 하시겠습니까? (0) | 2020.10.24 |
목록의 요소를 분할하는 방법은 무엇입니까? (0) | 2020.10.24 |
반복하는 동안 Python dict 수정 (0) | 2020.10.24 |
hg log-마지막 5 개의 로그 항목을 가져 오는 방법은 무엇입니까? (0) | 2020.10.24 |