11

コンストラクターに少し問題があります。私のヘッダーファイルでは、次のように宣言しています。

char short_name_[2]; 
  • およびその他の変数

私のコンストラクタで:

Territory(std::string name, char short_name[2], Player* owner, char units);
void setShortName(char* short_name);
inline const char (&getShortName() const)[2] { return short_name_; }

私のcppファイルでは:

Territory::Territory(std::string name, char short_name[2], Player* owner, 
                     char units) : name_(name), short_name_(short_name), 
                    owner_(owner), units_(units)
{ }

私のエラー:

Territory.cpp: コンストラクター 'Territory::Territory(std::string, char*, Player*, char)': Territory.cpp:15:33: エラー: 'char*' を 'char に代入する際に互換性のない型 [ 2]'</p>

私はすでにそれを理解しましたchar[2] <=> char*が、コンストラクターと get/setter についてこれを処理する方法がわかりません。

4

3 に答える 3

18

C++ の raw 配列は、厄介で危険をはらんでいます。これが、非常に正当な理由がない限り、std::vectorまたはを使用する必要がある理由ですstd::array

まず、他の人が言ったように、char[2]と同じではないchar*か、少なくとも通常はそうではありません。char[2]は のサイズ 2 の配列でcharありchar*、 へのポインタcharです。配列は必要に応じて最初の要素へのポインターに減衰するため、混乱することがよくあります。したがって、これは機能します:

char foo[2];
char* bar = foo;

しかし、逆はそうではありません:

const char* bar = "hello";
const char foo[6] = bar; // ERROR

関数パラメーターを宣言するときに混乱を招くのはchar[]char*. したがって、コンストラクターでは、パラメーターchar short_name[2]は実際にはchar* short_name.

配列のもう 1 つの癖は、他の型のようにコピーできないことです (これは、関数パラメーター内の配列がポインターとして扱われる理由の 1 つの説明です)。たとえば、次のようなことはできません。

char foo[2] = {'a', 'b'};
char bar[2] = foo;

代わりに、の要素を繰り返し処理してにfooコピーするbarか、次のような関数を使用する必要がありますstd::copy

char foo[2] = {'a', 'b'};
char bar[2];
// std::begin and std::end are only available in C++11
std::copy(std::begin(foo), std::end(foo), std::begin(bar));

したがって、コンストラクターでは、の要素を手動でにコピーする必要がありshort_nameますshort_name_

Territory::Territory(std::string name, char* short_name, Player* owner, 
                     char units) : name_(name), owner_(owner), units_(units)
{ 
    // Note that std::begin and std::end can *not* be used on pointers.
    std::copy(short_name, short_name + 2, std::begin(short_name));
}

ご覧のとおり、これはすべて非常に煩わしいので、よほどの理由がない限り、そのままstd::vectorの配列 (またはこの場合はおそらくstd::string) の代わりに使用する必要があります。

于 2013-04-10T00:15:08.430 に答える
2

関数が引数として配列を必要とする場合、代わりに配列の最初の要素へのポインターを取得します。このポインタは配列ではなくポインタであるため、配列の初期化には使用できません。

配列への参照を引数として受け入れる関数を作成できます。

void i_dont_accept_pointers(const char (array&)[2]) {}

ここでの問題は、この配列参照を使用して別の配列を初期化できないことです。

class Foo {
  char vars[2];
  Foo(const char (args&)[2])
    : vars(args)  // This will not work
  {}
};

C++ 11 はstd::array、この問題やその他の配列の問題を解消するために導入されました。古いバージョンでは、配列要素を反復処理して個別にコピーするか、std::copy.

于 2013-04-09T23:45:41.713 に答える