C++, 클래스 상속할때 함수 다형성 상실? 되는게 맞나요?

tien770의 이미지

class Base
{
public:
void f(int) {}
void f() {}
};

class Derived : public Base
{
public:
// something
};

class DerivedAgain : public Derived
{
public:
void f() {}
};

Base b;
b.f();
b.f(1);

Derived d;
d.f();
d.f(1);

DerivedAgain a;
a.f();
a.f(1); // compile error

간단한 테스트 코드입니다.

Base 클래스에서 f()는 인자형태가 다르게 두가지로 정의되어 있습니다. 당연히 두가지 모두 사용이 가능합니다.
Derived 클래스로 상속받아서도 두가지 모두 사용하는것이 가능합니다.
DerivedAgain 클래스로 상속받으면서는 f() 중에 하나를 재정의합니다.
이 때부터는 함수의 다형성은 상실되고 새로 정의한 하나만 사용이 가능합니다.
즉, 위의 코드에서 마지막 줄은 컴파일에러가 발생합니다.

virtual 사용해서 가상함수로 바꾸고 테스트를 해 보아도 마찬가지입니다.
혹시 제 컴파일러만 이상한걸까요? ㅎㅎ (VC++ 2010 Express 사용중입니다만)

한참 쉬다가 오랜만에 코딩 좀 해보려 했더니, 이런것도 가물가물하네요.
vtable 어쩌고 관련해서 원래 저렇게 되어있는건가요?

tien770의 이미지

소스 이쁘게 줄 맞춰 놓았는데, 그대로 올리는 방법이 뭔지도 모르겠군요 ㅠㅠ

세벌의 이미지

code

#include<stdio.h>
int main()
{
    return 0;
}
tien770의 이미지

흐음... 그러니까 그게...
소스를 박스 안에 넣는 방법이 굼금한거라는.. ^^

qiiiiiiiip의 이미지

이미 아시겠지만..

<code> ... < /code>

안에 넣으세요.... ( 공백없이.. )
< > 대신 [ ] 도 됩니다.
tien770의 이미지

예번에 분명 배웠던걸텐데...
나이 먹을수록 하나씩 까먹네요 ^^

neocoin의 이미지

저도 참 신기해서 찾아 봤는데요. DerivedAgain::f() 가 선언되면서 부모의 f를 모두 overload 해서 숨겨버리네요.

그래서 override 하고 싶은 메소드는 명시적으로 네임 스페이스에 선언해 줘야하나봐요. 그러니까 이런식으로요.

class DerivedAgain : public Derived                                                 
{                                                                                   
  public:                                                                           
    using Base::f;  // or using Derived:f;                                                                
    void f() {}                                          
}; 

스펙을 좀 더 살펴봐야겠는데, 요즘에는 cpp 를 안하고 있어서, 일단 여기까지만 알아봤습니다.
(스펙에 근거한 정확한 이유는 다른 분께 부탁드려요. )
overload 와 override 가 섞여서 이러는거 같은데, 이런 형태를 조심해야겠다는 다짐을 하게되었습니다.

어쨌든 참 신기합니다.

참고 문서

http://stackoverflow.com/questions/2973976/c-inheritance-and-method-overloading
http://www.parashift.com/c++-faq-lite/hiding-rule.html

tien770의 이미지

네.. 조심해야겠어요.
인터페이스 설계해놓은게 살짝 틀어지고 있는 중이랍니다 ㅎ

bluekyu의 이미지

저도 이상해서 찾아 봤습니다.

Stackoverflow (http://stackoverflow.com/questions/1628768/why-does-an-overridden-function-in-the-derived-class-hide-other-overloads-of-the)에 비슷한 문제가 있는데, 더 정확하게 알아보고 싶어서 The C++ Programming Language 책에 찾아보았습니다.

7.4.2 절에 따르면, 오버로딩의 경우 서로 다른 유효범위에 선언된 함수는 오버로딩되지 않는다고 합니다.
Base class 하고 Derive class 간의 유효범위가 다르기 때문에 Base 클래스의 함수들이 오버로딩 되지 않아서 문제가 발생하는 거라고 생각 됩니다.
책의 예제는 아래와 같습니다.

void f(int);
 
void g()
{
    void f(double);
    f(1);    // f(double) is called!
}

/*** Signature ******************
* blog: http://blog.bluekyu.me/ *
********************************/

tien770의 이미지

그러게나 말입니다.
C 에서의 저 규칙이 클래스 상속에도 묘하게 적용되어 있군요 ^^

yielding의 이미지

A function member of a derived class is not in the same scope as a function member of the same name in a base class.

 
[Example:
class B {
public:
    int f(int);
 };
 
class D : public B {
public:
   int f(char*);
};
 
Here D::f(char*) hides B::f(int) rather than overloading it.
 
void h(D* pd)
{
    pd->f(1);     // error:
                  // D::f(char*) hides B::f(int)
    pd->B::f(1);  // OK
    pd->f("Ben"); // OK, calls D::f 
}
—end example]
}

Life rushes on, we are distracted

tien770의 이미지

그렇게 hide되고 있으니, 예제 적어주신 것처럼 소속을 명시해서 쓰는 수밖에 없겠군요.
분명 예전에는 다 공부했던 것일텐데
몇년 쉬다가 다시 앉으니 가물가물하네요 ㅎㅎ

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.