【问题标题】:pointer to const vs usual pointer (for functions)指向 const 的指针与通常的指针(用于函数)
【发布时间】:2009-07-13 05:55:17
【问题描述】:

指向 const 的指针和通常的函数指针之间有什么区别吗?什么时候适合对独立函数使用 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++ 没有给出警告。这就是我问的原因。

【问题讨论】:

    标签: c++ function-pointers


    【解决方案1】:

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

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

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

    这是我的主张的证据。 C++03,8.3.5/1

    cv-qualifier-seq 只能是非静态成员函数的函数类型、成员指针所指的函数类型或函数 typedef 声明的顶级函数类型的一部分。函数声明器中 cv-qualifier-seq 的效果与在函数类型之上添加 cv-qualification 不同,即它不会创建 cv-qualified 函数类型。事实上,如果在确定类型的任何时候形成了一个 cv 限定的函数类型,那么程序就是非良构的。

    这是 C++1x 的文本,8.3.5/7n2914:

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

    上面说下面是有效的,但是,它为可以声明 const 成员函数的函数创建函数类型。

    typedef void Ft() const;
    struct X { Ft cMemFn; };
    void X::cMemFn() const { }
    

    【讨论】:

    • 嘿,我说的是那个标准的专家。 :P
    • 呵呵,我是标准文本。但我很高兴你喜欢这个分析:)
    • C++98 包含与 '03 修订版相同的文本。那里的格式也不正确:)
    • 奇怪的是,即使使用-std=c++98 标志,g++ 也没有发出警告。
    • 试试-pedantic 标志,它会给我一个警告。
    【解决方案2】:

    根据定义,独立函数是 const。因此 const 和非 const 函数指针之间没有区别。

    【讨论】:

    • 标准中是否有一些信息说忽略独立函数的限定符。我找不到。
    • 我不知道这个标准中是否有任何内容。
    • 我已经尽力回答了,但我觉得有更好的地方,比如它明确指出functions are const
    【解决方案3】:

    我想你的意思是,
    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.
    

    -贾格纳特。

    【讨论】:

    • 没有。我的意思正是我写的。
    • @jia3ep:那你的标题和描述写错了。 “指向 X 的 const 指针”表示“X * const”;而“指向 const X 的指针”表示“const X *”。你应该先把它做好。
    • 我已经修正了标题和描述。
    • 虽然我的英语很差,但 C++ 是一种通用语言。这就是我用 C++ 编写示例的原因 :)
    • 这可能不是本意,但这是一个有趣且有用的说明。
    【解决方案4】:

    有趣的是,即使在指向 member 函数的指针上使用 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】:

      我认为之前的回复存在基本的误解。

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

      也就是说sum_func_cptr是一个指向函数的常量指针,也就是说你可以用一个非常量的成员函数来初始化它,但是你以后不能把它改成指向另一个函数,因为const指的是到变量。 这相当于:

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

      你不同意吗? :-)

      -保罗

      【讨论】:

      • 没有 const 限定的函数类型。所以const sum_func stuff = &amp;Foo::sum; 没有意义,正如我的回答中引用的标准所说。说sum_func * const sum_func_cptr = &amp;Foo::sum;this 是一个 const 函数指针)也是无效的,因为您尝试将成员函数指针分配给函数指针。你必须这样做sum_func Foo::* const sum_func_cptr = &amp;Foo::sum;
      • 我以上一篇文章为例。它将新类型“sum_func”定义为指向成员函数的指针: typedef int (Foo::*sum_func)(int,int);我的观点是,添加到“sum_func”的“const”不会将其更改为“pointer-to-const-member-function”。坦率地说,我什至不知道如何编写 typedef。而且我不知道你可以单独定义函数类型,只能定义函数的指针。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多