2010-01-13 6 views
6

기본 클래스에 의해 정의 된 가상 함수 세트를 부분적으로 재정의하는 데 문제가 있습니까? ,C++에서 부분 클래스 함수 재정의 문제

class MyBaseClass 
{ 
public: 
    virtual void setValue(int); 
    virtual void setValue(SpecialType*); 
} 

class MyDerivedClass : public MyBaseClass 
{ 
public: 
    virtual void setValue(int); 
} 

이 경고를 제거하는 가장 쉬운 방법은 기본 기능에 다른 이름을 사용하는 것입니다

overloaded virtual function "MyBaseClass::setValue" is only partially overridden in class "MyDerivedClass". 

클래스는 다음과 같이 :

제 컴파일러는 다음과 같은 경고를 제공합니다 그러나 나는이 특별한 경고를 고칠만한 강력한 이유가 있는지 알고 싶었다. 나는 이것이 C++ 표준을 위반한다고 생각하지 않는다. 필자는 프로그래머에게 가능한 모든 입력 유형에 대한 동작을 구현하는 것을 잊어 버렸을 것이라고 경고하는 것입니다. 우리의 경우 특정 유형의 일부를 제외하는 것이 의도적입니다.

이 경고가 표시되지 않도록 하시겠습니까?

+0

은 기본 기능에 다른 이름을 사용을 고려하는 경우는 이렇게합니다. MyBaseClass :: setValue (int)는 MyDerivedClass :: setValue (int)와는 다른 개념을 가지고 있으며 나쁘다고합니다. 가상 함수는 기본과 파생에서 동일한 작업을 수행해야합니다. 그렇지 않으면 사소한 변경 사항으로 인해 찾기 힘든 버그를 얻을 수 있습니다. –

+0

제 경우에는 개념 상 동일한 일을하고 있습니다. 이름 바꾸기는 깨끗하게 보이지 않는 setValueFromInt() setValueFromSpecialType()과 같은 것일 수 있습니다. 나는 대답 중 하나에서 설명하는 using 문을 사용하는 것을 선호합니다. 현재이 접근 방식을 조사하고 있습니다. –

답변

13

setValue(int)에 대한 재정의 기본 클래스합니다 (C++ FAQ Lite 참조) setValue(SpecialType*) 숨 깁니다, 그래서 당신은 setValue(new SpecialType())를 호출 할 경우 오류가 발생합니다.

당신은 파생 클래스에 using 지시문을 추가하여이를 방지 할 수있는 "수입"기본 클래스에서 오버로드 :

class MyDerivedClass : public MyBaseClass 
{ 
public: 
    using MyBaseClass::setValue; 
    virtual void setValue(int); 
}; 
+0

+1 실제로 전문화에 관심이없는 버전을 다시 작성하지 않는 방법을 보여주기 위해 +1. –

+0

using 문이 나에게 적합합니다. 나는 여러 플랫폼을 개발 중이다. 이 특정 코드 문제에 대해 Microsoft Visual Studio 6.0에서 불만을 토로하는 데 문제가 있습니다. 가장 엄격한 경고 수준에도 불구하고 불만을 제기 할 수는 없습니다. 누구든지이 컴파일러에서 경고를 내뿜는 방법을 알고 있습니까? –

6

경고가 정확합니다. 이름 숨기기입니다. MyDerivedClass 유형의 변수는 setValue(SpecialType*)을 호출 할 수 없습니다. 이제


내가 노골적으로 someone else's blog을 벗어 버리고 갈거야 :

가 과부하와 이름이 브래드 지난 밤과 전화 통화에서 C++

을 숨어, 그는 이상한에 대해 이야기 문제는 그가 새로운 C++ 작업에서 겪었던 문제입니다. 물론 광범위한 C++ 경험을 가진 사람들에게는 큰 문제가 아니지만 관리되는 코드 세계에 사는 사람들에게는 이상한 것처럼 보입니다.

C++에서 오버로드 된 메서드 (멤버 함수, 원하는대로 무엇이든)가있는 클래스가 있고 그 메서드를 확장 및 재정의하는 경우 오버로드 된 메서드를 모두 재정의해야합니다.

나는 하위 클래스에서 메소드 서명을 변경하여 설정된 인터페이스를 무효화하는 경우를 이해합니다. 그러나이 경우 인터페이스를 변경하지 않고 선택적으로 재정의하므로 직관력이 떨어집니다. 어느 쪽이 다른가. 예를 들어

두 가지 방법 (또는 오버 방법) 여기

class FirstClass 
{ 
public: 
     virtual void MethodA (int); 
     virtual void MethodA (int, int); 
}; 

void FirstClass::MethodA (int i) 
{ 
    std::cout << "ONE!!\n"; 
} 

void FirstClass::MethodA (int i, int j) 
{ 
    std::cout << "TWO!!\n"; 
} 

간단한 클래스. 당신이 SecondClass의 인스턴스를 사용할 때

이제
class SecondClass : public FirstClass 
{ 
public: 
    void MethodA (int); 
}; 

void SecondClass::MethodA (int i) 
{ 
    std::cout << "THREE!!\n"; 
} 

는, 대부분의 자바 나 C# 프로그래머가 호출 할 수 가정 할 수 있습니다 : 다음 계속 있도록, 두 매개 변수 버전을 대체하려면

두 매개 변수 MethodA가 표시되지 않기 때문에
int main() 
{ 
    SecondClass a; 
    a.MethodA (1); 
    a.MethodA (1, 1); 
} 

그러나, 두 번째 호출은 작동하지 않습니다. 포인터를 가져 와서 FirstClass로 업 캐스팅 할 수 있지만 SecondClass 인스턴스는 오버라이드되지 않은 메소드를 직접 상속하지 않습니다.

0

그것은 컴파일러가 경고를하고 싶어 분명하다 : 당신이 서브 클래스를 생성하는 int을 주면 다르게 동작하지만 SpecialType*을 주면 동작이 변경되지 않습니다.

일 수도 있고 일 수도 있지만 변경된 동작이 다른 오버로드 된 가상 기능에도 필요합니다.

나는 컴파일러가 나를 더 세게 경고했으면 좋겠다. 나는 그것을 무시했다! 오버라이드 된 메소드가 내 시나리오에서 컴파일되고 작동하는 것으로 판명되었지만 오버로드가 오버라이드되지 않기 때문에 다른 시나리오가 잘못되었다.

경고를 사용 중지하기 전에 두 번 생각해보십시오!

원래 동작을 유지하려는 경우, 그냥 부모 함수를 호출하는 것은 쉽다 : 꼭

class MyDerivedClass : public MyBaseClass { 
    virtual void setValue(int); 
    // explicit: keep original behavior for SpecialType 
    virtual void setValue(SpecialType* p) { MyBaseClass::setValue(p); } 
}; 
+0

나는 경고가 중요하며 잘못 될 수있는 것에 대해 경고하려고한다는 것을 알고 있습니다. 제 질문의 의도는 디자이너가 경고를하는 것이 왜 중요한지, 그리고 경고를 무시하거나 소음으로 인해 발생할 수있는 함정을 알아내는 것이 었습니다. –