Как вызвать статический метод из частного базового класса?
Из-за компоновки сторонней библиотеки у меня есть что-то вроде следующего кода:
struct Base
{
static void SomeStaticMethod(){}
};
struct Derived1: private Base {};
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
Base::SomeStaticMethod();
}
};
int main() {
Derived2 d2;
d2.SomeInstanceMethod();
return 0;
}
Я получаю ошибку компилятора C2247 с MSVC:
Base:: SomeStaticMethod недоступен, поскольку Derived1 использует private для наследования от Base.
Я знаю, что не могу получить доступ Base
члены из Derived2
через наследование из-за частного спецификатора, но я все еще должен иметь возможность вызывать статический метод Base
- независимо от каких-либо наследственных отношений между Base
а также Derived2
,
Как устранить неоднозначность и сообщить компилятору, что я просто вызываю статический метод?
5 ответов
Сделай это:
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
::Base::SomeStaticMethod();
// ^^
// Notice leading :: for accessing root namespace.
}
};
Я думаю, что ответ michalsrb лучше, но для полноты:
namespace
{
void SomeStaticMethodProxy()
{
return Base::SomeStaticMethod();
}
}
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
SomeStaticMethodProxy();
}
};
тоже будет работать.
Другие ответы дают способ решить проблему, я постараюсь объяснить, что происходит. Это из-за введенного имени класса.
9,2 (N4594)
[...] Имя класса также вставляется в область действия самого класса; это известно как имя введенного класса. В целях проверки доступа имя введенного класса обрабатывается так, как если бы оно было публичным именем члена.[...]
Обратите внимание, что даже если вы введете Base::SomeStaticMethod()
очевидно SomeStaticMethod
ищется в Base
область (это квалифицированное имя), но имя Base
Само по себе также нужно искать как-то(в этом примере как неквалифицированное имя (потому что оно не появляется после оператора разрешения области видимости))
Что происходит, когда вы ищете (неквалифицированное) имя Base
в Derived2
, первый Derived2
область поиска, затем Derived1
область поиска и затем Base
область поиска ищется и, наконец, вводится-имя-класса. Затем происходит контроль доступа (потому что контроль доступа происходит после поиска имени), и он обнаружит, что имя, которое вы искали, Base
член, который не доступен из Derived2
,
Вы можете сделать это, если хотите вызвать его через иерархию:
struct Derived1: private Base {
protected:
using Base::SomeStaticMethod;
};
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
Derived1::SomeStaticMethod();
}
};
В противном случае, сделайте, как упомянуто @michalsrb, если вы хотите вызвать его напрямую Base
,
Пара возможностей:
Не используйте структуру наследования для вызова метода. использование
::Base::SomeStaticMethod()
называть это.Base
доступен в глобальном пространстве имен.Принеси
private
функция в пространство именDerived1
написавusing Base::SomeStaticMethod;