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;
}