ä¸å…许æˆå‘˜å‡½æ•°çš„éžæŒ‡é’ˆtypedef?

时间:2011-09-15 10:37:49

标签: c++ compiler-errors function-pointers typedef member-function-pointers

在得到this question的答案åŽï¼Œæˆ‘å‘现有两ç§æœ‰æ•ˆçš„方法å¯ä»¥è¾“入定义函数指针。

typedef void (Function) ();
typedef void (*PFunction) ();

void foo () {}

Function * p = foo;
PFunction  q = foo;

我现在更喜欢Function * p到PFunction q,但显然这对指针到æˆå‘˜å‡½æ•°ä¸èµ·ä½œç”¨ã€‚考虑这个人为的例å­ã€‚

#include <iostream>

struct Base {
    typedef void (Base :: *Callback) ();
                        //^^^ remove this '*' and put it below (i.e. *cb)
    Callback cb;

    void go () {
        (this->*cb) ();
    }

    virtual void x () = 0;

    Base () {
        cb = &Base::x;
    }
};

struct D1 : public Base {
    void x () {
        std :: cout << "D1\n";
    }
};

struct D2 : public Base {
    void x () {
        std :: cout << "D2\n";
    }
};  

int main () {
    D1 d1;
    D2 d2;
    d1 .go ();
    d2 .go ();
}

但如果我将其更改为新的首选样å¼ï¼štypedef void (Base :: Callback) ()å’ŒCallback * cb,我会在typedef

处收到编译错误
  

æˆå‘˜'回调'上的é¢å¤–资格'Base ::'

Demo for error

为什么ä¸å…许这样åšï¼Ÿè¿™åªæ˜¯ä¸€ç§ç–忽还是会导致问题?

3 个答案:

答案 0 :(得分:10)

对于éžæˆå‘˜å‡½æ•°ï¼Œtypedef void(Function)()等类型有多ç§ç”¨é€”,但对于æˆå‘˜å‡½æ•°ï¼Œå”¯ä¸€çš„应用是声明一个包å«å‡½æ•°æŒ‡é’ˆçš„å˜é‡ã€‚因此,除了风格å好之外,没有严格的需è¦å…许这ç§è¯­æ³•ï¼Œå¹¶ä¸”它已从标准中çœç•¥ã€‚

背景

::是作用域解æžè¿ç®—符,如果X::Y是类类型,则语法staticä¿ç•™ç”¨äºŽXæˆå‘˜è®¿é—®ã€‚因此,X::*Z是å¦ä¸€ç§ç”¨äºŽå®šä¹‰æŒ‡å‘æˆå‘˜æŒ‡é’ˆçš„语法。

忘记æˆå‘˜å‡½æ•°ä¸€æ®µæ—¶é—´ï¼Œåªè¦æƒ³ä¸€æƒ³ member-data ,看看这段代ç ï¼š

struct X
{
   int a;
};

int X::*pa = &X::a; //pointer-to-member
X x = {100}; //a = 100
cout << (x.*pa) << endl;

它定义了一个指å‘æˆå‘˜æ•°æ®çš„指针,而cout使用它æ¥æ‰“å°å¯¹è±¡açš„{​​{1}}的值,它打å°ï¼š

x

演示:http://www.ideone.com/De2H1

现在想想,如果100 (而ä¸æ˜¯X::pa)被å…许这样åšï¼Œé‚£ä¹ˆä½ å·²ç»å°†ä¸Šè¿°å†…容写æˆï¼š

X::*pa

看到这ç§è¯­æ³•ï¼Œæ‚¨å¦‚何判断int X::pa = X::a; //not &X::a 是X::aæˆå‘˜è¿˜æ˜¯éžé™æ€æˆå‘˜ï¼Ÿè¿™å°±æ˜¯æ ‡å‡†æ出指å‘æˆå‘˜æŒ‡é’ˆè¯­æ³•çš„一个原因,并将其统一应用于éžé™æ€æˆå‘˜æ•°æ®ä»¥åŠéžé™æ€æˆå‘˜å‡½æ•°ã€‚

事实上,您无法撰写static,您需è¦æ’°å†™X::a。语法&X::a会导致编译错误(请å‚阅this)。


现在将 member-data 的这个å‚数扩展到 member-function 。å‡è®¾ä½ æœ‰ä¸€ä¸ªtypedef定义为:

X::a

那么您认为以下代ç æ˜¯åšä»€ä¹ˆçš„?

typedef void fun();

好å§ï¼Œå®ƒå®šä¹‰ç±»åž‹struct X { fun a; }; çš„æˆå‘˜a(函数ä¸å¸¦å‚数,返回void),并且相当于:

fun

惊讶?请继续阅读。

struct X
{
   void a();
};

我们å¯ä»¥ä½¿ç”¨å®Œå…¨ç›¸åŒçš„语法æ¥å¼•ç”¨çŽ°åœ¨æ˜¯æˆå‘˜å‡½æ•°çš„struct X { fun a; //equivalent to this: void a(); }; void X::a() //yes, you can do this! { cout << "haha" << endl; } :

a

相似性是å³ä¾§çš„synatax:X x; x.a(); //normal function call void (X::*pa)() = &X::a; //pointer-to-member (x.*pa)(); //using pointer-to-member 。 &X::a是指æˆå‘˜å‡½æ•°è¿˜æ˜¯æˆå‘˜æ•°æ®ï¼Œè¯­æ³•æ˜¯ç›¸åŒçš„。

演示:http://www.ideone.com/Y80Mf

<强>结论:

我们知é“无论a是æˆå‘˜æ•°æ®è¿˜æ˜¯æˆå‘˜å‡½æ•°ï¼Œæˆ‘们都无法在RHS上编写X::a。唯一å…许的语法是a,这使得目标类型(在LHS上)必须也必须是指针,这å过æ¥ä½¿è¯­æ³•&X::fç»å¯¹å¿…è¦å’ŒåŸºç¡€ï¼Œå› ä¸ºå®ƒç¬¦åˆè¯­è¨€ä¸­çš„其他语法。

答案 1 :(得分:2)

准确地说,éžæˆå‘˜æŒ‡é’ˆçš„两个typedef是ä¸ä¸€æ ·çš„:

typedef void function();
typedef void (*fptr)();

第一个将function定义为ä¸å¸¦å‚数的函数并返回void ,而第二个将ftpr定义为函数获å–的指针没有å‚数并返回void 。由于函数类型将在许多上下文中éšå¼è½¬æ¢ä¸ºæŒ‡é’ˆç±»åž‹ï¼Œå› æ­¤å¯èƒ½ä¼šäº§ç”Ÿæ··æ·†ã€‚但ä¸æ˜¯å…¨éƒ¨ï¼š

function f;            // declares void f();
struct test {
   function f;         // declares void test::f()
};
void g( function f );  // declares g( void (*f)() ): function decays to pointer to function in declaration
g( f );                // calls g( &f ): function decays to pointer to function
void f() {}            // definition of f
// function h = f;     // error: cannot assign functions
function *h = f;       // f decays to &f

答案 2 :(得分:0)

让我们跳过“功能â€éƒ¨åˆ†ä¸€ç§’钟。在C ++中,我们有int,int*å’Œint Foo::*类型。这是一个常规整数,指å‘整数的指针,以åŠæŒ‡å‘æ•´æ•°æˆå‘˜çš„指针。没有第四ç§ç±»åž‹çš„“整数æˆå‘˜â€ã€‚

完全相åŒçš„函数:å³ä½¿æœ‰å‡½æ•°ç±»åž‹ï¼Œå‡½æ•°æŒ‡é’ˆç±»åž‹å’Œæˆå‘˜å‡½æ•°æŒ‡é’ˆç±»åž‹ï¼Œä¹Ÿæ²¡æœ‰ç±»åž‹â€œæˆå‘˜å‡½æ•°â€ã€‚