web-dev-qa-db-ja.com

C ++でグローバル関数をどのように定義しますか?

クラスのメンバーではなく、どのクラスからもアクセス可能な関数が欲しいです。

私は#include関数が宣言されているヘッダーファイルですが、そのようなグローバル関数をどこで定義するのかわかりません。

そもそもそのような機能を持つことに対して正当な理由はありますか?

21
Cory Klein

ボディが必要です(cppファイル内):

int foo()
{
    return 1;
}

また、ヘッダーファイルの定義/プロトタイプは、関数を使用する前に含まれます。

#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
    int foo();
#endif

それを他の場所で使用する:

#include foo.h
void do_some_work()
{
    int bar = foo();
}

または、インライン関数を使用します(インライン化されることを保証しませんが、fooなどの小さな関数に役立ちます)。

#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
    inline int foo()
    {
        return 1;
    }
#endif

あるいは、Cスタイルのヘッダーベースの関数を悪用することもできます(これによりヘッダーになり、staticが強制的に単一のコンパイルユニットにのみ存在するようにしますただし):

#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
    static int foo()
    {
        return 1;
    }
#endif
26
Necrolis

あなたが呼び出しているものグローバル関数は通常無料関数と呼ばれ、 A Good Thing です。

クラスのメンバー関数のように定義しますが、そのクラスのスコープ外に定義します。

double squared(double x) {
    return x*x;
}

ヘッダーファイルでinlineキーワードを使用して定義するか、単にそこに宣言できる単純な関数

double squared(double x);

実装(最初の例)を*.cppファイルに配置します。

6

ヘッダーファイル:

// someheader.h
#ifndef MY_GLOBAL_FUN
#define MY_GLOBAL_FUN

void my_global_fun();    

#endif

実装ファイル内:

#include "someheader.h"

void my_global_fun()
{
    // ...
}

その機能を必要とする他のファイル:

#include "someheader.h"

void f()
{
    my_global_fun();
}

このような無料の関数は有用であり、それらを使用することに対する多くの議論はありません。ユースケースによっては、これらの関数を特定のnamespaceに入れて、使用している他のライブラリとの名前の衝突を回避することが適切である可能性があります。

3
Chad

Main()を考えてください。関数はちょっと...そこにあります。クラス、構造体、または名前空間内にはありません。あなたはただ宣言し、それに体を与えます。もちろん、メインではない関数の場合は、ヘッダーにプロトタイプを置き、.cppファイルで定義するのが最善です。

Cにはクラスがなく、構造体にはメンバー関数を保持できなかったことを思い出してください。当時は無料の機能に問題はありませんでしたが、今はありません。

0
MGZero

プロトタイプをヘッダーファイルで宣言し、実装ファイルで定義する必要があります。

//file.h
void foo();

//file.cpp
void foo ()
{}

2番目の質問に簡単に答えるには、いくつかの異なるクラスや型で一般的な方法で使用されるグローバル関数が必要です。たとえば、数学関数。

それ以外の場合、一般に、非常に多くのグローバル関数を回避できます。また、staticローカルメンバーまたはそのような関数に関連付けられたグローバルデータを持つことは避けてください(スレッドの安全性について心配する必要はありません)。

0
iammilind

@Necrolisによる回答に加えて、名前のない名前空間を支持してstaticの使用は推奨されません。ただし、名前のない名前空間と静的の両方を使用すると、翻訳単位ごとに個別のコピーが作成され、バイナリのサイズが大きくなります。この意味では、インラインの使用はこれらの両方よりも優れています。

これらのソリューションは、コンパイラーによる使用固有の最適化をより多く可能にしますが、ソースファイルで定義してからリンクする場合と比較して、命令キャッシュにやさしいものではありません。

0