17.7 Calling inherited functions and overriding behavior
https://www.learncpp.com/cpp-tutorial/calling-inherited-functions-and-overriding-behavior/
Calling a base class function
derived class object의 member function을 호출한다면,
컴파일러는 먼저 derived class에 member function이 있는지 찾아볼 것이다
만약 존재하지 않는다면 inheritance chain을 타고 올라고 member가 존재하는지 찾아볼 것이다
class Base
{
protected:
int m_value {};
public:
Base(int value)
: m_value { value }
{
}
void identify() const { std::cout << "I am a Base\n"; }
};
class Derived: public Base
{
public:
Derived(int value)
: Base { value }
{
}
};
int main()
{
Base base { 5 };
base.identify();
Derived derived { 7 };
derived.identify();
return 0;
}
위의 출력의 결과는 다음과 같다
I am a Base
I am a Base
main에서 derived.identify가 호출되면 Derived에서 찾아보고 존재하지 않기에 Base로 넘어갔다
Redefining behaviors
하지만 만약 우리고 Derived class에서 identify를 정의하면 이를 대신 사용한다
class Derived: public Base
{
public:
Derived(int value)
: Base { value }
{
}
int getValue() const { return m_value; }
// Here's our modified function
void identify() const { std::cout << "I am a Derived\n"; }
};
위와 같이 identify를 재정의 했다
따라서 출력은 다음과 같다
I am a Base
I am a Derived
재정의된 함수는 재정의된 access specifier를 따르게 된다
따라서 Base에서 private 함수 였어도
Derived에서 public으로 재정의 되면 호출에 문제가 없다
반대로 Base에서는 public 이더라도
Derived에서 private이라면 Derived object에서 접근할 때 private으로 간주하므로 불가능하다
Adding to existing functionality
때로는 우리는 Base의 functionality를 유지한 채로 Derived만의 기능을 덧붙이고 싶을 때가 있다
앞서 말한 사례는 모두 Derived::identify()가 Base::identify()를 hide하는 경우였다
만약 기능을 조금 추가하고 싶은 경우라면 다음과 같이 재정의할 수 있다
class Derived: public Base
{
public:
Derived(int value)
: Base { value }
{
}
int getValue() const { return m_value; }
void identify() const
{
Base::identify(); // call Base::identify() first
std::cout << "I am a Derived\n"; // then identify ourselves
}
};
Base::identify()를 호출하기에 기능을 추가할 수 있게 되었다
그런데 우리는 왜 scope resolution operator(::)(범위지정연산자)가 필요한 것일까?
만약 Base::를 prefix로 하지 않는다면 다음과 같다
class Derived: public Base
{
public:
Derived(int value)
: Base { value }
{
}
int getValue() const { return m_value; }
void identify() const
{
identify(); // Note: no scope resolution!
cout << "I am a Derived";
}
};
이때 Derived::identify내부에서 identify()를 호출하는데
여기서 Base::가 없으므로 자동으로 identify()는 Derived::identify를 호출한다
따라서 무한재귀가 되는 것이다
friend
만약 friend로 지정된 함수를 위와 같이 재정의 하고 싶다면 어떻게 해야할까?
#include <iostream>
class Base
{
private:
int m_value {};
public:
Base(int value)
: m_value{ value }
{
}
friend std::ostream& operator<< (std::ostream& out, const Base& b)
{
out << "In Base\n";
out << b.m_value << '\n';
return out;
}
};
class Derived : public Base
{
public:
Derived(int value)
: Base{ value }
{
}
friend std::ostream& operator<< (std::ostream& out, const Derived& d)
{
out << "In Derived\n";
// static_cast Derived to a Base object, so we call the right version of operator<<
out << static_cast<const Base&>(d);
return out;
}
};
int main()
{
Derived derived { 7 };
std::cout << derived << '\n';
return 0;
}
위의 사례는 operator overloading을 redefined한 것이다
그런데 Base의 functioanlity도 사용하고 싶기에 static_cast를 이용해 추가해주고 있다
따라서 출력은 다음과 같다
In derived
In base
7
Author And Source
이 문제에 관하여(17.7 Calling inherited functions and overriding behavior), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ikmy0ung/17.7-Calling-inherited-functions-and-overriding-behavior저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)