C++ 如何使用cout打印函数指针?

C++ 如何使用cout打印函数指针?,c++,C++,我想用cout打印出一个函数指针,但发现它不起作用。 但是在我将函数指针转换为(void*)之后,它就工作了,带有%p的printf也是如此,例如 #include <iostream> using namespace std; int foo() {return 0;} int main() { int (*pf)(); pf = foo; cout << "cout << pf is " << pf <<

我想用cout打印出一个函数指针,但发现它不起作用。 但是在我将函数指针转换为(void*)之后,它就工作了,带有%p的printf也是如此,例如

#include <iostream>
using namespace std;

int foo() {return 0;}

int main()
{
    int (*pf)();
    pf = foo;
    cout << "cout << pf is " << pf << endl;
    cout << "cout << (void *)pf is " << (void *)pf << endl;
    printf("printf(\"%%p\", pf) is %p\n", pf);
    return 0;
}
#包括
使用名称空间std;
int foo(){return 0;}
int main()
{
int(*pf)();
pf=foo;

cout您可以将函数指针视为该函数机器代码中第一条指令的地址。任何指针都可以视为
bool
:0为false,其他所有内容均为true。正如您所观察到的,当转换为
void*
并作为流插入运算符的参数提供时(
您可以将函数指针视为该函数机器代码中第一条指令的地址。任何指针都可以被视为
bool
:0为false,其他所有内容均为true。正如您所观察到的,当转换为
void*
并作为流插入运算符的参数提供时(<代码> > p>实际上存在一个超负荷的实际上,有一个超负荷的

指针指向<代码>(空洞*)<代码>,如果你想看到它们的值,在C++中做正确的事情(TM)是正确的事(t/p)。

< p>铸造指针指向<代码>(空洞*)< /C> >将它们打印到<代码> cOUT/COD>是正确的(TM)要在C++中做,如果你想看到它们的值。< /P> < P>关于你的编辑,你可以通过通过<代码>未签名char < /Cube指针访问它来打印任何内容。
#include <iostream>
#include <iomanip>

struct foo { virtual void bar(){} };
struct foo2 { };
struct foo3 : foo2, foo { virtual void bar(){} };

int main()
{
    void (foo3::*p)() = &foo::bar;

    unsigned char const * first = reinterpret_cast<unsigned char *>(&p);
    unsigned char const * last = reinterpret_cast<unsigned char *>(&p + 1);

    for (; first != last; ++first)
    {
        std::cout << std::hex << std::setw(2) << std::setfill('0')
            << (int)*first << ' ';
    }
    std::cout << std::endl;
}
#包括
#包括
结构foo{virtualvoidbar(){}};
结构foo2{};
结构foo3:foo2,foo{virtualvoidbar(){}};
int main()
{
void(foo3::*p)(=&foo::bar;
unsigned char const*first=重新解释强制转换(&p);
unsigned char const*last=reinterpret_cast(&p+1);
for(;first!=last;++first)
{

std::cout关于编辑,您可以通过
unsigned char
指针访问任何内容来打印内容。指向成员函数的指针示例如下:

#include <iostream>
#include <iomanip>

struct foo { virtual void bar(){} };
struct foo2 { };
struct foo3 : foo2, foo { virtual void bar(){} };

int main()
{
    void (foo3::*p)() = &foo::bar;

    unsigned char const * first = reinterpret_cast<unsigned char *>(&p);
    unsigned char const * last = reinterpret_cast<unsigned char *>(&p + 1);

    for (; first != last; ++first)
    {
        std::cout << std::hex << std::setw(2) << std::setfill('0')
            << (int)*first << ' ';
    }
    std::cout << std::endl;
}
#包括
#包括
结构foo{virtualvoidbar(){}};
结构foo2{};
结构foo3:foo2,foo{virtualvoidbar(){}};
int main()
{
void(foo3::*p)(=&foo::bar;
unsigned char const*first=重新解释强制转换(&p);
unsigned char const*last=reinterpret_cast(&p+1);
for(;first!=last;++first)
{

关于你的具体问题

我们怎样才能观察一份报告的内容 成员函数指针

答案是,除了将它们转换为bool以表示它指向某个对象或不指向某个对象之外,您不能“观察者”成员函数指针。至少不能以兼容的方式。原因是该标准明确禁止:

4.12脚注57:

57)货币兑换规则 指向成员的指针(从指针到 指向的成员的指针的基成员 派生)与 指向对象的指针的规则(从 指向派生的指针(指向基的指针) (4.10,第10条)。此倒置为 确保类型安全所必需的。注意 指向成员的指针不是 指向对象的指针或指向对象的指针 函数和转换规则 这些指针的任何一个都不适用于 指向成员的指针。尤其是 无法转换指向成员的指针 空荡荡的*

例如,下面是示例代码:

#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;

class Gizmo
{
public:
    void DoTheThing()
    {
        return;
    };


private:
    int foo_;
};

int main()
{
    void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;

    Gizmo g;
    (g.*fn)();  // once you have the function pointer, you can call the function this way

    bool b = fn;
//  void* v = (void*)fn;    // standard explicitly disallows this conversion
    cout << hex << fn;
    return 0;
}

关于你的具体问题,

我们怎样才能观察一份报告的内容 成员函数指针

答案是,除了将它们转换为bool以表示它指向某个对象或不指向某个对象之外,您不能“观察者”成员函数指针。至少不能以兼容的方式。原因是该标准明确禁止:

4.12脚注57:

57)货币兑换规则 指向成员的指针(从指针到 指向的成员的指针的基成员 派生)与 指向对象的指针的规则(从 指向派生的指针(指向基的指针) (4.10,第10条)。此倒置为 确保类型安全所必需的。注意 指向成员的指针不是 指向对象的指针或指向对象的指针 函数和转换规则 这些指针的任何一个都不适用于 指向成员的指针。尤其是 无法转换指向成员的指针 空荡荡的*

例如,下面是示例代码:

#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;

class Gizmo
{
public:
    void DoTheThing()
    {
        return;
    };


private:
    int foo_;
};

int main()
{
    void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;

    Gizmo g;
    (g.*fn)();  // once you have the function pointer, you can call the function this way

    bool b = fn;
//  void* v = (void*)fn;    // standard explicitly disallows this conversion
    cout << hex << fn;
    return 0;
}

在C++11中,可以通过定义
运算符的可变模板重载来修改此行为。在C++11中,可以通过定义
运算符的可变模板重载来修改此行为(有一次我与函数的地址相交)
(决定之一)

#包括
#包括
void-alexf();
int main()
{ 
整数输出;
printf(“printf(\“%%p\”,pf)是%p\n”,alexf);
asm(“movl%[输入],%%eax\n”
“movl%%eax,%[输出]\n”
:[输出]“+m”(整数输出)
:[input]“r”(&alexf)
:“eax”、“ebx”
);
std::cout可能(在一段时间内,我一直在讨论函数的地址)
(决定之一)

#包括
#包括
void-alexf();
int main()
{ 
整数输出;
printf(“printf(\“%%p\”,pf)是%p\n”,alexf);
asm(“movl%[输入],%%eax\n”
“movl%%eax,%[输出]\n”
:[输出]“+m”(整数输出)
:[input]“r”(&alexf)
:“eax”、“ebx”
);

std::cout+1。唯一适用于函数指针的标准转换是(左值到右值的转换除外)到
bool
的转换。值得注意的是,您必须执行
重新解释
才能转换
int(*)()<代码> >代码> Vult*/Cux> .avaar有一个文档覆盖函数指针的转换规则吗?最终文件将是C++标准,第4节[CONV]和5.2 [Exp.PoST ]。标准不是免费的,但您可以得到最新草案H。
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;

class Gizmo
{
public:
    void DoTheThing()
    {
        return;
    };

    **void DoTheOtherThing()
    {
        return;
    };**


private:
    int foo_;
};

int main()
{
    void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;

    Gizmo g;
    (g.*fn)();  // once you have the function pointer, you can call the function this way

    bool b = fn;
//  void* v = (void*)fn;    // standard explicitly disallows this conversion
    cout << hex << fn;

    **void(Gizmo::*fnOther)(void) = &Gizmo::DoTheOtherThing;

    bool same = fnOther == fn;
    bool sameIsSame = fn == fn;**

    return 0;
}
#include<iostream>
namespace function_display{
template<class Ret, class... Args>
std::ostream& operator <<(std::ostream& os, Ret(*p)(Args...) ){ // star * is optional
    return os << "funptr " << (void*)p;
}
}

// example code:
void fun_void_void(){};
void fun_void_double(double d){};
double fun_double_double(double d){return d;}

int main(){
    using namespace function_display;
    // ampersands & are optional
    std::cout << "1. " << &fun_void_void << std::endl; // prints "1. funptr 0x40cb58"
    std::cout << "2. " << &fun_void_double << std::endl; // prints "2. funptr 0x40cb5e"
    std::cout << "3. " << &fun_double_double << std::endl; // prints "3. funptr 0x40cb69"
}