2009-07-13 15 views
5

関数へのポインターと通常ポインターの間に違いはありますか?スタンドアローン関数にconst修飾子を使用するのが適切な場合何の警告を与えない++constへのポインターvs通常のポインター(関数用)

#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; 
}

グラム:

は、私は私の質問を説明するために、短いサンプルを書きました。それが私が尋ねる理由です。

答えて

12

あなたのコードはC++ 03に関して病気-形成です。 では、const(またはvolatile)修飾された関数型を構築することはできません。あなたがするたびに、あなたのプログラムは不正な形になります。

この規則は、const/volatileを無視して、コンパイラをC++ 1xの場合はhas been changedにします。 C++コンパイラは通常、C++ 03モードでもこの規則を実装しています。したがって、次の2つは同じ関数を2回定義し、コンパイルエラーになります。

typedef void Ft(); 


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

ここに私の主張の証拠があります。 C++ 03、

CV-修飾子-配列のみ非静的メンバ関数のための関数型の一部でなければならない8.3.5/1、メンバへのポインタが指す、またはトップレベルの関数型への関数型関数typedef宣言の関数宣言子でのcv-qualifier-seqの効果は、関数型の上にcv-qualificationを追加することと同じではありません。つまり、cv修飾された関数型を作成しません。実際に、タイプの決定においていつでもcv修飾された関数タイプが形成されれば、プログラムは不正な形になる。ここ

C++ 1X、8.3.5/7 n2914ためにそのテキストである:

CV-クアリのfi ER-seqが唯一の非スタティックメンバ関数のための関数型、機能型の一部でなければなりませんメンバへのポインタが参照する関数型、または関数typedef宣言のトップレベル関数型です。関数宣言子のcv-qualifier-seqの効果は、関数型の上にcv-qualificationを追加するのと同じではありません。後者の場合、cv-qualifierは無視されます。

上記では、以下が有効であり、constメンバ関数を宣言できる関数の関数型を作成することを示しています。

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

ねえ、私が話していたスタンダードの専門家がいます。 :P – GManNickG

+0

Hehe、私は標準的なテキストでn00bです。しかし、私は分析が好きで嬉しいです:) –

+0

私はC++ 98の標準を読んだことがあります。それが私がそれを見つけることができなかった理由です。 –

1

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

いいえ、私はまさに私が書いたことを意味しました。 –

+1

@ jia3ep:あなたのタイトルと説明が間違って書いてあります。 "const pointer to X"は "X * const"を意味します。 「const Xへのポインタ」は「const X *」を意味します。あなたはまずそれを得なければなりません。 – newacct

+0

私はタイトルと説明を修正しました。 –

6

スタンドアロン関数は、定義によってconstです。したがって、const関数ポインタと非const関数ポインタの間に違いはありません。

+0

スタンダードにスタンドアロン機能の修飾子を無視するという情報がありますか?私は見つけることができません。 –

+0

私はこのために標準の中に何かがあるかどうかわかりません。 – Naveen

+0

私は自分の答えで最善を尽くしましたが、明示的に 'function are const'と書かれているような、より良いものがあると感じています。 – GManNickG

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; 
} 
0

以前の回答には基本的な誤解がありました。 sum_func_cptrconstを指しているためそれは、あなたが非constメンバ関数で初期化することができますが、別の関数にポイントに、後でそれを変更することはできませんで、関数への定数ポインタであることを意味

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

変数に追加します。 これは以下のものと同等です:

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

あなたは同意しますか? :-)

-Paolo

+0

const修飾された関数型はありません。だから、 'const sum_func stuff =&Foo :: sum;'は私の答えの標準の引用が言うように、意味をなさない。メンバ関数ポインタを関数ポインタに代入しようとするので、 'sum_func * const sum_func_cptr =&Foo :: sum;'(* thisはconst関数ポインタです)と言っても意味がありません。あなたは 'sum_func Foo :: * const sum_func_cptr =&Foo :: sum;'をしなければなりません。 –

+0

私は例として前の投稿を取った。これは、新しい型 "sum_func"をメンバ関数へのポインタとして定義します: typedef int(Foo :: * sum_func)(int、int); "sum"に "const"を追加しても、 "const-member-functionへのポインタ"に変更されませんでした。 正直言って、私はそのtypedefを書いてもわかりません。関数型だけを定義でき、関数へのポインタだけを定義できるかどうかは分かりませんでした。 – Paolo

関連する問題