указатель на const против обычного указателя (для функций) - PullRequest
5 голосов
/ 13 июля 2009

Есть ли разница между указателем на 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 ++ не выдает предупреждений. Вот почему я спрашиваю.

Ответы [ 5 ]

12 голосов
/ 13 июля 2009

Ваш код плохо сформирован относительно C ++ 03. Вы можете не когда-либо создать постоянный (или изменчивый) квалифицированный тип функции. Всякий раз, когда вы делаете, ваша программа становится плохо сформированной.

Это правило было изменено для 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-qualifier-seq должен быть только частью типа функции для нестатической функции-члена, типа функции, к которому относится указатель на член, или типа функции верхнего уровня объявления функции typedef. Эффект cv-qualifier-seq в деклараторе функции - это не то же самое, что добавление cv-qualification поверх типа функции, то есть он не создает cv-квалифицированный тип функции. Фактически, если в любое время при определении типа формируется квалифицированный по типу cv тип функции, программа является некорректной.

Вот этот текст для C ++ 1x, 8.3.5/7 n2914:

cv-qualifer-seq должен быть только частью типа функции для нестатической функции-члена, типа функции, к которому относится указатель на член, или типа функции верхнего уровня объявления функции typedef. Влияние cv-квалификатора-seq в деклараторе функции - это не то же самое, что добавить cv-квалификацию поверх типа функции. В последнем случае cv-квалификаторы игнорируются.

Выше сказано, что приведенное ниже является допустимым, и создает тип функции для функции, которая может объявить функцию-член const.

typedef void Ft() const;
struct X { Ft cMemFn; };
void X::cMemFn() const { }
6 голосов
/ 13 июля 2009

Автономные функции являются постоянными по определению. Следовательно, нет разницы между константным и неконстантным указателем на функцию.

1 голос
/ 13 июля 2009

Я думаю, что вы имели в виду,
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.

0 голосов
/ 15 июля 2009

Я думаю, что в предыдущих ответах было основное недоразумение.

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

Это означает, что sum_func_cptr является постоянным указателем на функцию, то есть вы можете инициализировать его неконстантной функцией-членом, но вы не можете изменить ее позже, чтобы указать на другую функцию, поскольку const относится к переменной. Это эквивалентно:

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

Ты не согласен? : -)

-Paolo

0 голосов
/ 13 июля 2009

Интересно отметить, что спецификатор 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...