此代码:
class B {
protected:
void Foo(){}
}
class D : public B {
public:
void Baz() {
Foo();
}
void Bar() {
printf("%x\n", &B::Foo);
}
}
给出了这个错误:
t.cpp: In member function 'void D::Bar()':
Line 3: error: 'void B::Foo()' is protected
顺便说一句:This looks related但是我正在寻找一个参考指标或类似内容的参考(希望这将导致如何按照我期望的方式工作)
答案 0 :(得分:20)
您可以通过D
代替&D::Foo
来填写&B::Foo
地址。
看到这个编译很好:http://www.ideone.com/22bM4
但是这不会编译(你的代码):http://www.ideone.com/OpxUy
为什么我可以调用受保护的方法但不取其地址?
您无法通过撰写&B::Foo
来获取其地址,因为Foo
是受保护的成员,您无法从外部B
访问它,甚至不能访问其地址。但是写&D::Foo
,你可以,因为Foo
通过继承成为D
的成员,你可以得到它的地址,无论它是私有的,受保护的还是公共的。
&B::Foo
与b.Foo()
和pB->Foo()
具有相同的限制,在以下代码中:
void Bar() {
B b;
b.Foo(); //error - cannot access protected member!
B *pB = this;
pB->Foo(); //error - cannot access protected member!
}
请参阅ideone上的错误:http://www.ideone.com/P26JT
答案 1 :(得分:5)
这是因为派生类的对象只能访问基类的受保护成员(如果它是相同的对象)。允许您使用受保护成员函数的指针将使得无法保持此限制,因为函数指针不会随身携带任何此类信息。
答案 2 :(得分:3)
我相信protected
不像你在C ++中那样工作。在C ++ protected
中,只允许访问其自身实例的父成员,而不是父类的任意实例。如其他答案中所述,获取父函数的地址将违反此规定。
如果要访问父项的任意实例,可以让父类成为子项的朋友,或者创建父方法public
。没有办法改变protected
的含义来做你想在C ++程序中做的事情。
但是你真的试图在这做什么?也许我们可以为你解决那个问题。
答案 3 :(得分:3)
为什么我可以调用受保护的方法但不能使用其地址?
这个问题有误。你不能打电话
B *self = this;
self->Foo(); // error either!
另一个答案是,如果您通过D
,然后访问非静态受保护成员,则可以。也许您想阅读this?
总结一下,请阅读this issue report。
答案 4 :(得分:1)
你的帖子没有回答"为什么我可以 调用受保护的方法但不采取 它的地址?"
class D : public B {
public:
void Baz() {
// this line
Foo();
// is shorthand for:
this->Foo();
}
void Bar() {
// this line isn't, it's taking the address of B::Foo
printf("%x\n", &B::Foo);
// not D:Foo, which would work
printf("%x\n", &D::Foo);
}
}
答案 5 :(得分:0)
有没有办法在派生类中标记完全可访问的内容,而不是只能从派生类中访问并与所述派生类相关?
是的,passkey idiom。 :)
class derived_key
{
// Both private.
friend class derived;
derived_key() {}
};
class base
{
public:
void foo(derived_key) {}
};
class derived : public base
{
public:
void bar() { foo(derived_key()); }
};
由于只有derived
可以访问derived_key
的构造函数,因此只有该类可以调用foo
方法,即使它是公开的。
这种方法的明显问题是,您需要与每个可能的派生类相关,这很容易出错。另一种可能的(在你的情况下更好的方式)是与基类交朋友并公开受保护的get_key
方法。
class base_key
{
friend class base;
base_key() {}
};
class base
{
public:
void foo(base_key) {}
protected:
base_key get_key() const { return base_key(); }
};
class derived1 : public base
{
public:
void bar() { foo(get_key()); }
};
class derived2 : public base
{
public:
void baz() { foo(get_key()); }
};
int main()
{
derived1 d1;
d1.bar(); // works
d1.foo(base_key()); // error: base_key ctor inaccessible
d1.foo(d1.get_key()); // error: get_key inaccessible
derived2 d2;
d2.baz(); // works again
}
请参阅完整示例on Ideone。