• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    해결됨

공변 반환형에 대해서 질문이 하나 더 있습니다.

22.10.31 16:13 작성 조회수 251

0

#include <iostream>
#include <string_view>

class Base
{
public:
	// This version of getThis() returns a pointer to a Base class
	virtual Base* getThis() { std::cout << "called Base::getThis()\n"; return this; }
	void printType() { std::cout << "returned a Base\n"; }
};

class Derived : public Base
{
public:
	// Normally override functions have to return objects of the same type as the base function
	// However, because Derived is derived from Base, it's okay to return Derived* instead of Base*
	Derived* getThis() override { std::cout << "called Derived::getThis()\n";  return this; }
	void printType() { std::cout << "returned a Derived\n"; }
};

int main()
{
	Derived d{};
	Base* b{ &d };
	d.getThis()->printType(); // calls Derived::getThis(), returns a Derived*, calls Derived::printType
	b->getThis()->printType(); // calls Derived::getThis(), returns a Base*, calls Base::printType

	return 0;
}

공변반환형이 잘 이해되지 않아서 https://www.learncpp.com/cpp-tutorial/the-override-and-final-specifiers-and-covariant-return-types/ 에서 한 번 더 공부를 해봤는데요

There is one special case in which a derived class virtual function override can have a different return type than the base class and still be considered a matching override.

If the return type of a virtual function is a pointer or a reference to some class, override functions can return a pointer or a reference to a derived class. These are called covariant return types.

One interesting note about covariant return types: C++ can’t dynamically select types, so you’ll always get the type that matches the actual version of the function being called.

Now the interesting case. We then call b->getThis(). Variable b is a Base pointer to a Derived object. Base::getThis() is a virtual function, so this calls Derived::getThis().

Although Derived::getThis() returns a Derived*, because Base version of the function returns a Base*, the returned Derived* is upcast to a Base*.

Because Base::printType() is non-virtual, Base::printType() is called.

파생 클래스의 virtual function 오버라이드가 기본 클래스의 return 타입과 다른 return 타입을 가지면서 여전히 매치되는 오버라이드라고 생각되는 특별한 경우가 하나 있다.

만약 virtual function의 return 타입이 어떤 클래스의 포인터나 레퍼런스라면 오버라이드 함수들은 그 클래스의 파생 클래스의 포인터나 레퍼런스를 return할 수 있다. 이러한 것들을 공변 반환형이라고 부른다.

공변 반환형에 대해서 한 가지 흥미로운 사실이 있다. C++가 동적으로 타입을 선택할 수가 없어서 호출되는 함수의 원래 버전의 타입을 항상 갖는다는 것이다.

이제 흥미로운 경우이다. 우리는 b->getThis()를 호출한다. b는 Derived 객체의 Base 포인터이다. Base::getThis()는 virtual function이라서 Dervied::getThis()를 호출한다.

비록 Dervied::getThis()가 Dervied*를 반환할 지라도 Base 버전의 함수는 Base*를 return하기 때문에 Dervied*는 Base*로 upcast된다.

그리고 Base::printType()은 non-virtual function이기 때문에 그냥 Base::printType()이 호출된다.

이렇게 해석을 해보았는데 One interesting note about covariant return types: C++ can’t dynamically select types, so you’ll always get the type that matches the actual version of the function being called. 이 부분에서 type이 의미하는게 return type을 의미하는 건지 아니면 자기 자신의 class type을 의미하는 건지 알고 싶습니다. 그리고 동적으로 타입을 선택할 수 없다는 게 무슨 의미인지도 알고 싶습니다.

답변 1

답변을 작성해보세요.

1

강민철님의 프로필

강민철

2022.11.01

안녕하세요,

 

One interesting note about covariant return types: C++ can’t dynamically select types, so you’ll always get the type that matches the actual version of the function being called.

볼드체한 부분에 의하면 (함수의) return type을 의미하는 것으로 보입니다.

 

그리고 동적으로 타입을 선택할 수 없다는 것은

말 그대로 아래의 dynamic typing(런타임에 타입이 결정)이 안되는 것을 의미한다고 봅니다.

https://wiki.c2.com/?DynamicTyping