clang에 의한 C ++ 과부하 가상 함수 경고? virtual void * get(char*

clang은 다음 코드를 컴파일 할 때 경고를 내 보냅니다.

struct Base
{
    virtual void * get(char* e);
//    virtual void * get(char* e, int index);
};

struct Derived: public Base {
    virtual void * get(char* e, int index);
};

경고는 다음과 같습니다.

warning: 'Derived::get' hides overloaded virtual function [-Woverloaded-virtual]

(물론 상기 경고를 활성화해야합니다).

이유를 모르겠습니다. Base에서 동일한 선언을 주석 해제하면 경고가 종료됩니다. 내 이해는 두 개의 get () 함수가 다른 서명을 갖기 때문에 숨길 수 없다는 것입니다.

clang이 맞습니까? 왜?

이것은 최신 버전의 Xcode를 실행하는 MacOS X에 있습니다.

clang --version
Apple LLVM version 5.0 (clang-500.1.74) (based on LLVM 3.3svn)

업데이트 : Xcode 4.6.3과 동일한 동작.



답변

이 경고는 재정의가 의도 된 경우 실수로 과부하를 숨기는 것을 방지하기위한 것입니다. 약간 다른 예를 고려하십시오.

struct chart; // let's pretend this exists
struct Base
{
    virtual void* get(char* e);
};

struct Derived: public Base {
    virtual void* get(chart* e); // typo, we wanted to override the same function
};

경고이므로 반드시 실수라는 의미는 아니지만 오류를 나타낼 수 있습니다. 일반적으로 이러한 경고는보다 명시 적으로 작성하고 컴파일러에게 사용자가 작성한 의도를 알 수 있도록하여 경고를 차단하는 수단이 있습니다. 이 경우 다음을 수행 할 수 있습니다.

struct Derived: public Base {
    using Base::get; // tell the compiler we want both the get from Base and ours
    virtual void * get(char* e, int index);
};


답변

구조체 공용 인터페이스를 그대로 유지하면서 경고를 비활성화하는 또 다른 방법은 다음과 같습니다.

struct Derived: public Base
{
    virtual void * get(char* e, int index);
private:
    using Base::get;
};

이렇게하면 소비자가 경고를 끄는 동안 Derived전화를 걸 수 없습니다 Derived::get(char* e).

Derived der;
der.get("", 0); //Allowed
der.get("");    //Compilation error


답변

R. Martinho Fernandes 솔루션은 실제로 get()단일 char * 인수를 사용 하는 메서드를 Derived범위 로 가져 오려는 경우 완벽하게 유효합니다 .

실제로 제공 한 스 니펫에는 가상 메소드가 필요하지 않습니다 (Base와 Derived는 동일한 서명을 가진 메소드를 공유하지 않기 때문에).

실제로 다형성이 필요하다고 가정해도 은폐 행동은 의도 한대로 될 수 있습니다. 이 경우 다음 pragma를 사용하여 Clang의 경고를 로컬로 비활성화 할 수 있습니다.

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
    // Member declaration raising the warning.
#pragma clang diagnostic pop


답변

경고는 Derived 클래스의 범위에 void * get (char * e) 함수가 없으므로 동일한 이름의 다른 메서드에 의해 숨겨 짐을 의미합니다. 파생 클래스에 지정된 이름의 메서드가 하나 이상 있으면 다른 인수가 있더라도 컴파일러는 기본 클래스의 함수를 검색하지 않습니다.

이 샘플 코드는 컴파일되지 않습니다.

class A
{
public:
    virtual void Foo() {}
};

class B : public A
{
public:
    virtual void Foo(int a) {}
};


int main()
{
    B b;
    b.Foo();
    return 0;
}


답변