programing

C ++ 가상 함수 반환 유형

nasanasas 2020. 10. 24. 10:21
반응형

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

반응형