如果C++ FAQ Lite中的以下内容为真:"函数名称衰减到指向函数的指针"(因为数组名称衰减为指向其第一个元素的指针); 为什么我们必须加入&符号?
typedef int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = &Fred::f;
Run Code Online (Sandbox Code Playgroud)
而不只是:
typedef int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = Fred::f;
Run Code Online (Sandbox Code Playgroud)
在第二种情况下,Fred :: f是一个函数,可以衰减到指向该函数的指针.
我希望这个问题不是那么愚蠢.
我想拥有类型特征,这将有助于我从成员函数指针中获取类的类型。我调查了这个答案 ,发现我已经达到目标了。
看起来像这样:
#include <iostream>
// example class
struct MyClass {
void funct() { std::cout << "funct has been called....\n"; }
};
// traits
template<typename Class> struct get_class{};
template<typename ReType, typename Class, typename... Args>
struct get_class<ReType(Class::*)(Args...)>
{
using type = Class;
};
template<typename Type> using get_class_t = typename get_class<Type>::type;
int main()
{
get_class_t<decltype(&MyClass::funct)> myObj;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---> this is a lot of typing
myObj.funct();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,如代码中所示,我每次都需要编写,get_class_t<decltype(&MyClass::funct)>
或者
auto ptr = &MyClass::funct;
get_class_t<decltype(ptr)> myObj;
// ^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
这很多decltype() …
我有一个回调机制,涉及的类是:
class App
{
void onEvent(const MyEvent& event);
void onEvent(const MyOtherEvent& event);
Connector connect;
}
class Connector
{
template <class T> void Subscribe(boost::function <void (const T&)> callback);
}
App::App()
{
connect.Subscribe<MyEvent>(&App::OnEvent<MyEvent>);
}
Run Code Online (Sandbox Code Playgroud)
首先这个代码不能编译,这是一个例子.
模板的使用使我的例子变得复杂,但是我把它们留下了,因为它影响了我的问题.我似乎确定我的订阅需要模板化,因为Connector类不知道它处理了多少事件类型.当我尝试创建一个:
boost::function f = &App::OnEvent,
Run Code Online (Sandbox Code Playgroud)
我尝试使用特化创建OnEvent作为模板函数,但似乎编译器将我的OnEvent函数视为重载而不是模板特化,否则如果我尝试将其明确声明为,则不会在命名空间错误中获取模板特化
template <> OnEvent(const MyEvent& e) ...
Run Code Online (Sandbox Code Playgroud)
我可以得到以下代码来编译:
boost::function <void (App*, const MyEvent&)> f = &App::OnEvent;
f(this, e);
Run Code Online (Sandbox Code Playgroud)
编译,运行和工作.
boost::function<void (const MyEvent&)> g = boost::bind(&App::OnEvent, this);
Run Code Online (Sandbox Code Playgroud)
才不是.我认为是因为我没有正确指定重载函数的地址.
现在已经向泰迪熊解释了这一切 - 我认为我的问题是"如何正确创建一个指向重载或模板化成员函数的函数指针并将此指针绑定到它?"
根据最近一个问题的以下答案,我可以使用函数指针从另一个类调用私有方法,如下所示(另请参见ideone)Foo<T>::foo()Bar
#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> …Run Code Online (Sandbox Code Playgroud) C++ 03可以让你有资格函数的参数为const,volatile和/或左值引用(&).
C++ 11增加了一个:rvalue references(&&).
此外,C++允许您根据参数的限定符重载函数,以便在调用函数时选择最合适的重载.
成员函数在概念上可以被认为是一个函数,它接受一个额外的参数,其类型是对它所属的类的实例的引用.可以基于此"额外参数"的限定符来重载成员函数,其方式与任何其他参数非常相似.这通过将限定符放在函数签名的末尾来表示:
struct Foo
{
int& data(); // return a non-const reference if `this` is non-const
const int& data() const; // return a const reference if `this` is const
};
Run Code Online (Sandbox Code Playgroud)
在C++ 03,const和volatile预选赛是可能的,C++ 11还允许&和&&(&理论上可以被允许在C++ 03,但它不是).
可以使用限定符的任何组合,除了&并且&&是互斥的,这使得C++ 03中的2 ^ 2 = 4种可能性和C++ 11中的2 ^ 4-4 = 12.
当你想使用成员函数指针时,这可能会非常痛苦,因为它们在这些限定符中甚至不是多态的:this作为参数传递的成员函数指针的" 类型" 的限定符必须与那些完全匹配关于它被传递的参数的类型.C++也没有提供用于抽象限定符的明确工具.在C++ 03中,这基本上没问题,因为你必须编写一个const版本和一个非 …
我的问题不是从基类构造函数调用虚拟成员函数,而是指向虚方法成员函数的指针在基类构造函数中是否有效.
鉴于以下内容
class A
{
void (A::*m_pMember)();
public:
A() :
m_pMember(&A::vmember)
{
}
virtual void vmember()
{
printf("In A::vmember()\n");
}
void test()
{
(this->*m_pMember)();
}
};
class B : public A
{
public:
virtual void vmember()
{
printf("In B::vmember()\n");
}
};
int main()
{
B b;
b.test();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于所有兼容的c ++编译器,这会产生"In B :: vmember()"吗?
给定一个对象:
struct foo {
void func();
};
Run Code Online (Sandbox Code Playgroud)
现在给出模板化的函数声明:
template<typename T, T F>
void bar();
Run Code Online (Sandbox Code Playgroud)
所以bar将采用这样的成员函数:
bar<decltype(&foo::func), &foo::func>()
Run Code Online (Sandbox Code Playgroud)
在机身的bar我要恢复的数据类型foo的T.我能这样做吗?我希望能够做到这样的事情:
get_obj<T> myfoo;
(myfoo.*F)();
Run Code Online (Sandbox Code Playgroud)
我知道这get_obj不是一件事,但有没有办法写出来?
假设我有一个可以保存基类方法地址的指针类型.我可以为其分配子类方法的地址并期望它正常工作吗?在我的情况下,我使用它与基类指针,对象的动态类型是派生类.
struct B
{
typedef void (B::*MethodPtr)();
};
struct D: public B
{
void foo() { cout<<"foo"<<endl; }
};
int main(int argc, char* argv[])
{
D d;
B* pb = &d;
//is the following ok, or undefined behavior?
B::MethodPtr mp = static_cast<B::MethodPtr>(&D::foo);
(pb->*mp)();
}
Run Code Online (Sandbox Code Playgroud)
在讨论static_cast时,标准说明了这一点:
5.2.9.9类型"指向Cv1 T类型D的成员的指针"的rvalue可以转换为类型为"指向cv2 T类型B的成员的指针"的rvalue,其中B是D的基类(第10节),如果a从"指向T类型B的成员的指针"到"指向T类型D的成员的指针"的有效标准转换存在(4.11),并且cv2与cv1具有相同的cv资格,或者更高的cv资格.63)空成员指针值(4.11)被转换为目标类型的空成员指针值.如果类B包含原始成员,或者是包含原始成员的类的基类或派生类,则指向成员的结果指针指向原始成员.否则,演员的结果是不确定的.[注意:虽然B类不需要包含原始成员,取消引用成员指针的对象的动态类型必须包含原始成员; 见5.5.]
和往常一样,我很难破译标准.它有点说没关系,但我不能100%确定上述文本是否真的适用于我的示例代码中的情况.
struct B
{
void (B::*pf)(int, int); // data member
B () : pf(&B::foo) {}
void foo (int i, int j) { cout<<"foo(int, int)\n"; } // target method
};
int main ()
{
B obj;
// how to call foo() using obj.pf ?
}
Run Code Online (Sandbox Code Playgroud)
在上面的测试代码中,pf是一个数据成员B.调用它的语法规则是什么?它应该是直截了当的,但我没有得到正确的匹配.例如,如果我尝试,obj.*pf(0,0);那么我得到:
error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘pf (...)’, e.g. ‘(... ->* pf) (...)’
Run Code Online (Sandbox Code Playgroud) 下一个例子的汇编:
class A
{
public:
void foo()
{
}
};
class B : private A
{
public:
using A::foo;
};
int main()
{
typedef void (B::*mf)();
mf func = &B::foo;
B b;
(b.*func)();
}
Run Code Online (Sandbox Code Playgroud)
失败并出现以下错误:
main.cpp||In function ‘int main()’:
main.cpp|18|error: ‘A’ is an inaccessible base of ‘B’
main.cpp|18|error: in pointer to member function conversion
Run Code Online (Sandbox Code Playgroud)
我知道A不是B的可访问基础,但我使用的是using关键字.它不应该允许访问函数foo吗?
标准中哪些相关段落阻止上述编译?
c++ member-function-pointers implicit-conversion private-inheritance
c++ ×10
templates ×3
c++11 ×2
boost ×1
metatype ×1
methods ×1
overloading ×1
polymorphism ×1
private ×1
qualifiers ×1
type-traits ×1