5

指向 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++ 没有给出警告。这就是我问的原因。

4

5 回答 5

12

您的代码在 C++03 方面格式错误您永远无法构造 const(或 volatile)限定的函数类型。每当你这样做时,你的程序就会变得不正确。

此规则针对 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-qualification 不同。在后一种情况下,cv 限定符被忽略。

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

typedef void Ft() const;
struct X { Ft cMemFn; };
void X::cMemFn() const { }
于 2009-07-13T08:32:04.603 回答
6

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

于 2009-07-13T06:11:19.147 回答
1

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

-贾格纳特。

于 2009-07-13T06:09:21.163 回答
0

有趣的是,即使在指向成员函数的指针上使用 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;
}
于 2009-07-13T06:39:20.027 回答
0

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

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

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

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

你不同意吗?:-)

-保罗

于 2009-07-15T13:12:55.180 回答