问题
Based on the following answer to a recent question, I'm able to use a function pointer in order to call the private method Foo<T>::foo()
from another class Bar
, as shown below (see also ideone)
#include <iostream>
template<typename T>
struct Bar
{
typedef void (T::*F)();
Bar( T& t_ , F f ) : t( t_ ) , func( f )
{
}
void operator()()
{
(t.*func)();
}
F func;
T& t;
};
template<typename T>
class Foo
{
private:
void foo()
{
std::cout << "Foo<T>::foo()" << std::endl;
}
public:
Foo() : bar( *this , &Foo::foo )
{
bar();
}
Bar<Foo<T> > bar;
};
int main()
{
Foo<int> foo;
}
This works on MSVC 2013 and GCC 4.8.3. Is it valid?
回答1:
Yes it is permissible, and it works.
C++ Programming by Bjarne Stroustoup
C++ protects against accident rather than deliberate circumvention (fraud)
Sure, you cannot directly/easily call private methods outside the class, but if you are making enough efforts, C++ will allow it.
回答2:
C++ standard says
11.1 A member of a class can be
(1.1) — private; that is, its name can be used only by members and friends of the class in which it is declared.
i.e. the access specifier is applied to the name, not the executable code. This makes sense if you think about it, since access specifiers are a compile-time construct.
回答3:
Yes, it is valid.
Bar.operator()()
is just using a pointer, not trying to use an identifier with private access specifier.
It does not matter how that pointer was initialized, as long as it points to the right function.
As an example, look at this:
#include <iostream>
struct A {
protected:
void hidden() { std::cout << "But I was hidden !?\n"; }
};
struct B : A {
using A::hidden; // Making it public
};
int main() {
B().hidden();
}
As an aside, don't use std::endl
unless you really want to flush the stream, as that's expensive.
Normally '\n'
suffices.
回答4:
It does matter.
Header File
class A;
typedef int (A::*handler)(int x);
struct handler_pair {
int code,
handler fn
}
class A {
...
private:
int onGoober(int x);
int onGomer(int x);
};
Source file
handler_pair handler_map[] = {
{0, &A::onGoober}, // these will complain about the method being private
{1, &A::onGomer}
};
Changing the handler_map to a static member in the class and initializing that way avoids the complaint.
Where you take the address of the member function is important.
来源:https://stackoverflow.com/questions/27537482/able-to-use-pointer-to-function-to-call-private-method-of-an-external-class