3

Qtで画像ビューアを書いています。ヘッダーファイルで次のことをしようとしています:

class ImageModel
{


private:
    const static std::vector<int> mZoomLevels;

}

ソースファイルで:

int zooms[] = {1,2,3,4,5,6,7,8,9,10};
const std::vector<int> mZoomLevels(zooms.begin(),zooms.end());

ただし、次のエラーが表示されます。

非クラス タイプ 'int[10]' の zooms のメンバー 'begin' のリクエスト 非クラス タイプ 'int[10]' の zooms のメンバー 'end' のリクエスト

この static const private メンバーを初期化する方法を知っている人はいますか?

4

5 に答える 5

5

Plain arrays do not have member functions. I believe you're looking for this:

int zooms[] = {1,2,3,4,5,6,7,8,9,10};
const std::vector ImageModel::mZoomLevels(zooms, zooms + 10);
于 2012-12-07T14:44:21.067 に答える
5

Arrays do not have begin and end members. You can use array name for begin and array name plus length for the end:

const std::vector mZoomLevels(zooms, zooms+10);

In C++11, you can use std::begin and std::end, like this:

const std::vector mZoomLevels(std::begin(zooms), std::end(zooms));

In both cases, it is a good idea to declare your zooms array file-static or hide it in a namespace, to make sure that its name does not "pollute" the global namespace.

于 2012-12-07T14:44:28.647 に答える
1

ここでは、C ++ 11にアクセスできるかどうかに応じて、さまざまなアプローチに従います。

C ++ 03では、プレーン配列(constであるため)を使用しますが、おそらくクラスではなく、実装ファイルのプライベート名前空間で使用します(プライベートであるため、1つの変換ユニットのみがのメンバーの定義ImageModel

// cpp
namespace {
   static int gZoomLevels[] = { 1, 2, ... };
}

std::vector<int>このアプローチを本当に使い続けたい場合はstd::vector、静的な期間で別の変数を作成せずに、メンバーを定義するヘルパー関数を翻訳ユニットに作成し、それを使用してを作成します。

namespace {
   static std::vector<int> chooseANameForInitializer() {
       int data[] = { 1, 2, 3 };
       return std::vector<int>( data, data + (sizeof data/sizeof *data) );
   }
}
const std::vector<int> ImageModel::mZoomLevels = chooseANameForInitializer();

C ++ 11std::array<int,...>では、代わりに使用します。これにより、動的割り当てと余分な間接参照のコストが回避されます。確かにそれは大きな利益ではありstd::vector<int>ませんが、それが提供する機能のいずれも必要としないときに持っている意味はありません。

class ImageModel
{
private:
    static const std::array<int,10> mZoomLevels;  
};
// cpp:
const std::array<int,10> ImageModel::mZoomLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

繰り返しますが、あなたが持っていることを主張するなら、あなたはリスト初期化std::vector<int>を使うことができます

const std::vector<int> ImageModel::mZoomLevels{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
于 2012-12-07T15:00:56.563 に答える
1

zooms は、メンバーとメソッドを持たない C スタイルの配列です。つまり、意味がzooms.beginありzooms.endません。C++11 互換のコンパイラを使用している場合はstd::begin(zooms)std::end(zooms)

于 2012-12-07T14:45:56.103 に答える
1

通常の C++ 配列はメンバーを持つことができません。ただし、静的ディスパッチを探しており、パラメーターの型によるオーバーロードの解決でうまく機能します。したがって、C++11 は非メンバー関数を提供std::beginします。std::end(これはすでに述べた。)

次のように、非メンバー関数を呼び出すためのベスト プラクティスに慣れてください (汎用テンプレート コードを記述するときに非常に役立ちます)。

using std::begin;
using std::end;

const std::vector mZoomLevels(begin(zooms), end(zooms));

これは、コンテナーの型に関係なく正しく機能しzooms、ADL (引数依存ルックアップ、Koenig ルックアップと呼ばれることもある) を利用して、カスタム クラス型がある場合は、同じ名前空間内のbeginおよびの実装を検索します。endzooms

ところで、std::beginこれらstd::endは C++11 で提供されていますが、以前のバージョンでも十分に簡単に独自のものを作成できます。

template <typename T, size_t N>
T* begin( T (&a)[N] ) { return a; }

template <typename T, size_t N>
T* end( T (&a)[N] ) { return a + N; }
于 2012-12-07T14:48:23.633 に答える