代码之家  ›  专栏  ›  技术社区  ›  Kirill V. Lyadvinsky

指向常量的指针与通常的指针(用于函数)

  •  5
  • Kirill V. Lyadvinsky  · 技术社区  · 15 年前

    指向常量的指针和函数的普通指针有什么区别吗?什么时候适合将const限定符用于独立函数?

    我写了简短的样本来说明我的问题:

    #include <iostream>
    using namespace std;
    
    int sum( int x, int y ) { return x + y; }
    typedef int sum_func( int, int );
    
    int main()
    {
        const sum_func* sum_func_cptr = &sum; // const function
        sum_func* sum_func_ptr = &sum;        // non-const function ?
    
        // What is the difference between sum_func_cptr and sum_func_ptr
    
        int x = sum_func_cptr( 2, 2 );
        cout << x << endl;
    
        int y = sum_func_ptr( 2, 2 );
        cout << y << endl;
    
        sum_func_cptr = 0;
        sum_func_ptr = 0;
    
        return 0;
    }

    G++没有给出警告。这就是我问的原因。

    5 回复  |  直到 15 年前
        1
  •  12
  •   Johannes Schaub - litb    15 年前

    您的代码是 病态的 关于C++ 03。你可以 构造一个const(或volatile)限定函数类型。每当你这样做,你的程序就会变得不正常。

    这条规则 has been changed 对于C++1x,使编译器忽略 const / volatile . C++编译器通常已经在C++ 03模式下实现这个规则。因此,下面两个函数将定义同一个函数两次,并导致编译错误。

    typedef void Ft();
    
    
    void f(Ft const*) { }
    void f(Ft *) { } // another definition!
    

    这是我索赔的证据。C++ 03, 8.3.5/1

    cv限定符seq只能是非静态成员函数、指向成员的指针所指向的函数类型或函数typedef声明的顶级函数类型的函数类型的一部分。函数声明符中的cv限定符seq的效果与在函数类型顶部添加cv限定符不同,即它不会创建cv限定函数类型。事实上,如果在确定一个类型时,任何时候都形成了一个cv限定的函数类型,那么这个程序就是格式错误的。

    这里是C++ 1x的文本, 8.3.5/7 N29

    cv qualifier seq只能是非静态成员函数的函数类型、指向成员的指针所指向的函数类型或函数typedef声明的顶级函数类型的一部分。函数声明符中的cv qualifier seq的e_e_e t与在函数类型上添加cv qualifier seq不同。在后一种情况下,将忽略CV限定符。

    上面说下面的内容是有效的,并且为一个可以声明const成员函数的函数创建函数类型。

    typedef void Ft() const;
    struct X { Ft cMemFn; };
    void X::cMemFn() const { }
    
        2
  •  6
  •   Naveen    15 年前

    独立函数的定义是常量。因此,常量和非常量函数指针之间没有区别。

        3
  •  1
  •   Nick Dandoulakis    15 年前

    我想你的意思是,
    sum_func* const sum_func_cptr 而不是 const sum_func* sum_func_cptr .

    sum_func* const sum_func_cptr = &sum;
    sum_func* const sum_func_cptr = &sum_new; // will not compile.
    // whereas,
    const sum_func* sum_func_cptr = &sum;  // will compile
    const sum_func* sum_func_cptr = &sum_new; // will compile.
    sum_func* sum_func_cptr = &sum;  // will compile
    sum_func* sum_func_cptr = &sum_new; // will compile.
    

    - Jagannath。

        4
  •  0
  •   avakar    15 年前

    有趣的是,即使在指针上使用const说明符,也似乎没有效果。 成员 功能。

    #include <iostream>
    using namespace std;
    
    class Foo {
    public:
      int sum( int x, int y ) {
        _x = x;
        _y = y;
        return x + y;
      }
    private:
      int _x;
      int _y;
    };
    
    typedef int (Foo::*sum_func)(int,int);
    
    int main()
    {
        Foo f;
        const sum_func sum_func_cptr = &Foo::sum; // const pointer
        sum_func sum_func_ptr = &Foo::sum;        // non-const pointer
    
        int x = (f.*sum_func_cptr)( 2, 2 );
        cout << x << endl;
    
        int y = (f.*sum_func_ptr)( 2, 2 );
        cout << y << endl;
    
        const sum_func* sum_func_cptr_cptr = &sum_func_cptr;
        sum_func* sum_func_ptr_ptr = &sum_func_ptr;
    
        x = (f.**sum_func_cptr_cptr)( 2, 2 );
        cout << x << endl;
    
        y = (f.**sum_func_ptr_ptr)( 2, 2 );
        cout << y << endl;
    
        return 0;
    }
    
        5
  •  0
  •   Paolo    15 年前

    我认为在以前的答复中有一个基本的误解。

        const sum_func sum_func_cptr = &Foo::sum; // const pointer
    

    那意味着 sum_func_cptr 是指向一个函数的常量指针,也就是说,可以用一个非常量成员函数初始化它,但以后不能将其更改为指向另一个函数,因为 const 引用变量。 相当于:

        sum_func const sum_func_cptr = &Foo::sum; // const pointer
    

    你不同意吗?-)

    -保罗