由于第三方库的布局,我有类似下面的代码:
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;
}
我在MSVC中遇到编译器错误C2247:
Base :: SomeStaticMethod无法访问,因为Derived1使用private从Base继承。
我知道由于私有说明符,我无法通过继承从Base
访问Derived2
成员,但我仍然可以调用Base
的静态方法 - 无论Base
和Derived2
之间是否存在任何继承关系
如何解决模糊性并告诉编译器我只是调用静态方法?
答案 0 :(得分:22)
这样做:
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
::Base::SomeStaticMethod();
// ^^
// Notice leading :: for accessing root namespace.
}
};
答案 1 :(得分:8)
我认为michalsrb的答案更好,但为了完整性:
namespace
{
void SomeStaticMethodProxy()
{
return Base::SomeStaticMethod();
}
}
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
SomeStaticMethodProxy();
}
};
也可以。
答案 2 :(得分:7)
其他答案提供了解决问题的方法,我将尝试解释发生了什么。这是因为 inject-class-name 。
9.2(N4594)
[...]类名也插入到类本身的范围内;这被称为注入类名。 出于访问检查的目的,注入类名被视为公共成员名称。 [...]
请注意,即使您键入Base::SomeStaticMethod()
,显然也会在SomeStaticMethod
范围内查找Base
(它的合格名称),但名称 {{1} }本身也必须以某种方式查找,(在此示例中为非限定名称(因为它不会在范围解析运算符后出现))
当您在Base
中搜索(未经验证的)名称Base
时,会搜索到第一个Derived2
范围,然后搜索Derived2
范围,然后{{搜索范围,最后找到 inject-class-name 。然后进行访问控制(因为访问控制发生在名称查找之后),并且它会找到您查找的名称是Derived1
的成员,而不是#39} ; t可从Base
访问。
答案 3 :(得分:5)
如果要通过层次结构调用它,可以执行此操作:
struct Derived1: private Base {
protected:
using Base::SomeStaticMethod;
};
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
Derived1::SomeStaticMethod();
}
};
否则,如果您想直接在Base
上调用它,请按@michalsrb提及。
答案 4 :(得分:4)
有几种可能性:
不要使用继承结构来调用该方法。使用::Base::SomeStaticMethod()
进行调用。 Base
可在全局命名空间中访问。
通过撰写private
Derived1
函数添加到using Base::SomeStaticMethod;
的命名空间中
醇>