访问受保护方法的方法指针
Access to method pointer to protected method?
代码:
class B {
protected:
void Foo(){}
}
class D : public B {
public:
void Baz() {
Foo();
}
void Bar() {
printf("%xn", &B::Foo);
}
}
给出如下错误:
t.cpp: In member function 'void D::Bar()':
Line 3: error: 'void B::Foo()' is protected
- 为什么我可以调用一个受保护的方法,但不能获取它的地址?
- 是否有一种方法可以标记从派生类完全可访问的东西,而不是仅从派生类和访问与所述派生类相关的东西?
BTW:这看起来是相关的,但我正在寻找一个参考,在规范或类似的地方调用它(并希望这将导致如何让事情按照我期望的方式工作)。
可以通过写&D::Foo
而不是&B::Foo
来获取D
的地址。
查看编译结果: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
这是因为派生类的对象只有在与基类相同的情况下才能访问基类的受保护成员。如果允许使用受保护成员函数的指针,则不可能维护此限制,因为函数指针不携带任何此类信息。
我相信protected
在c++中并不像你想象的那样工作。在c++中,protected
只允许访问自己的实例的父成员,而不是父类的任意实例。如其他答案所述,取父函数的地址将违反此规则。
如果你想访问父类的任意实例,你可以让父类成为子类的好友,或者让父方法成为public
。在c++程序中,没有办法改变protected
的含义来做你想让它做的事情。
但是你在这里真正想要做什么呢?也许我们可以帮你解决那个问题
为什么我可以调用一个受保护的方法,但不能获取它的地址?
这个问题有错误。也不能调用
B *self = this;
self->Foo(); // error either!
正如另一个答案所说,如果您通过D
访问非静态受保护成员,则可以。也许你想看看这个?
作为总结,请阅读此问题报告
你的帖子没有回答"为什么我可以。调用受保护的方法,但不使用它的地址吗?"
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("%xn", &B::Foo);
// not D:Foo, which would work
printf("%xn", &D::Foo);
}
}
是否有一种方法来标记从派生类完全可访问的东西,而不是只能从派生类访问,并与所述派生类相关?
是的,使用passkey习语。:)
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
}
标准参考:https://en.cppreference.com/w/cpp/language/access#Protected_member_access
When a pointer to a protected member is formed, it must use a derived class in its declaration:
struct Base {
protected:
int i;
};
struct Derived : Base {
void f() {
// int Base::* ptr = &Base::i; // error: must name using Derived
int Base::* ptr = &Derived::i; // OK
}
};
- 将一个类的方法指针存储到另一个类中
- 如何调用返回类方法指针的类方法
- 通过reinterpret_casting方法指针从指针调用派生类的方法。这是 UB 吗?
- 泛型方法指针.reinterpret_cast指向不同类的方法指针,这是 UB 吗?
- C++;类方法指针;λ;将 lambda 作为成员函数指针传递;
- 使用模板、方法指针和字符串键入推导
- 将方法指针作为整数参数发送到C#的C 方法
- 从C 中的VTable获取方法指针
- 模板化方法指针 - 无法匹配函数参数的指针
- 获取特定的模板重载方法指针
- 如何将方法指针声明为Typedef方法参数
- 如何将方法指针类型转换为函数指针类型
- 如何在使用 pthreads 时将方法指针作为函数参数传递C++
- 方法指针映射,编译器说他们不接受任何参数
- C# 方法指针,如 C++ 中的指针
- c++创建新的LinkedList类:Clear()方法指针被释放未分配
- 尝试获取类方法指针时出现E_NOINTERFACE
- 传递和强制转换方法指针
- 常量方法指针的类型是什么
- 将对象的方法指针传递给接受 [静态方法指针/全局函数] 指针的函数