2009-09-09 24 views
22

私はCインタビューの中で非常に興味深い質問をしました。特定のg()関数からしか呼び出せないような方法で関数f()をどのように実装できますか? g()以外の関数がf()を呼び出そうとすると、コンパイラエラーが発生します。Cで "private/restricted"関数を実装する方法は?

最初は、これは関数ポインタで行うことができましたが、実行時に呼び出しをブロックすることに近づけることができました。しかし、私はコンパイル時の戦略を考えることができませんでした。私はこれがansi Cを使用して可能かどうかも分かりません。

誰も考えていますか?

+0

質問はこれとまったく同じですか?それは私には意味をなさない。おそらくそれがメンバ関数の場合は、メリットがあるかもしれませんが、通常の関数ですか? – Suma

+0

@Suma:Cにメンバー関数はありません。 –

答えて

23

g()とf()を同じモジュールに置き、f()を静的として宣言します。 staticキーワードは、同じモジュールまたはソースファイル内の関数に対してのみf()を使用可能にします。

f()とg()で他のメソッドを使用できないようにする必要があります。そうでなければf()を呼び出すことができます。

PS - 私は本当にクリスLutzの答えが実際に最高だと思います。このアプローチに言及するだけでなく、より少ない環境条件で動作する巧妙なマクロの名前変更(これらの2つの機能のためにモジュールファイルを特に必要としない)も言及しています。

また、そのマクロで、次の操作を行うことができます注:

ときに、ユーザーのタイプF素敵なエラーメッセージ、および(Visual Studioのような)自動完了者は、その先端を示すだろう提示する
#define f() f_should_not_be_called_by_anything_except_g 

()。

+1

コメントを確認しました@John Milikinを作成しました。 – luizleroy

+0

私は認識しています。かなり簡単に修正することは、本当に。 –

+0

実際、私はジョナサン・レフラーの答えのファンですが、彼が言ったように一般化はできません。しかし、正しい(つまり、静的な)答えを言ったほとんどの人がアップしました。おそらく彼らが探していたものでしょう。 –

8

f()と同じソースファイルに、f()とを同じソースファイルに配置します。

+1

私はそれが予想される答えだとは思わない。これは誰も同じソースとcal f()内に他の関数を置くことを止めません。 – luizleroy

+17

あなたのソース機能を編集できる人なら誰でも何かをプライベートにするための*任意のスキームを克服することができます。 – dmckee

33

はここに1つの方法です:あなたはf()g()は、ファイル内の唯一の機能であることを保証することができれば、

int f_real_name(void) 
{ 
    ... 
} 

#define f f_real_name 
int g(void) 
{ 
    // call f() 
} 
#undef f 

// calling f() now won't work 

もう一つの方法は、staticとしてf()を宣言することです。

EDIT:コンパイルエラーを引き起こす別のマクロのトリック:

static int f(void) // static works for other files 
{ 
    ... 
} 

int g(void) 
{ 
    // call f() 
} 
#define f call function 

// f() certainly produces compiler errors here 
+1

しかし、f_real_name()を呼び出すことはできます。 –

+1

これは本当ですが、厳密には要件ではありません。ルールではなく、意図を果たしてください。 –

+3

もちろん、 'f_real_name()'を呼び出すことができます。 'printf()'、 'malloc()'、その他多くの素晴らしい関数を呼び出すこともできますが、 'f()'を呼び出すことと何が関係していますか? –

10

あなたはstaticキーワードでモジュール-プライベート関数を行うことができます。そして、

static void func(void) 
{ 
    // ... 
} 

func()は他の関数によって呼び出すことができます同じファイルに定義されています(技術的には、同じ変換単位#includeディレクティブで定義されている他の関数は引き続きアクセスできます) それ)。 func内部結合を有すると言われている。他のすべての機能(つまり、staticキーワードなし)は、外部リンケージと言われています。

それ以外では、機能をアクセスできないようにする方法はありません。マクロを使用して関数の名前を変更することはできますが、他のコードは常に適切な名前でアクセスできます。

2

偶然にのみ可能です。

関数f()とg()が同じソースファイル内にあり、ファイル内に他の関数が存在せず、g()がf()への関数ポインタをその呼び出し元f()を静的にするとジョブが実行されます。

他の関数が同じソースファイル内になければならない場合は、f()を静的関数としてファイルの最後に配置し、g()コンパイラに「宣言がありません」というエラーを生成するようには指示していませんでした。他の関数は警告でそれを呼び出すことができました。

#include <stdio.h> 

extern void g(void); /* in a header */ 

/* Other functions that may not call f() go here */ 

static void f(void) 
{ 
    puts("X"); 
} 

void g(void) 
{ 
    f(); 
} 

明らかに、この技術は、同じファイル内の関数の別のペアに確実に拡張することができない - X()とy() - X()とのみ、xは()(Yを呼び出すことができるように)G一方()とg()だけが同時にf()を呼び出すことができます。

しかし、通常は、プログラマーの規律に頼って、単にソースファイル内でf()を静的にし、g()だけが呼び出すことができるコメントを付けるようにします。 g()以外の関数はf()を呼び出します。

8

GCCのオプションはnested functionsです。それは標準Cではありませんが、かなりうまく動作します。

関連する問題