web-dev-qa-db-ja.com

カスタムクラスで配列を宣言するにはどうすればよいですか?

カスタムクラスで配列を宣言しようとしています。クラスにコンストラクターを追加すると、コンパイラーは「name [3]の初期化に一致するコンストラクターがない」と文句を言います。

私のプログラムは次のとおりです。

#include <iostream>

using namespace std;

class name {
  public:
    string first;
    string last;

  name(string a, string b){
    first = a;
    last = b;
  }
};

int main (int argc, const char * argv[])
{

  const int howManyNames = 3;

  name someName[howManyNames];

  return 0;
}

この実行を行うために私は何ができますか、そして私は何を間違っていますか?

13
Moshe

デフォルトのコンストラクタを提供する必要があります。その間、他のコンストラクタも修正します。

class Name
{
public:
  Name() { }
  Name(string const & f, string const & l) : first(f), last(l) { }
  //...
};

または、初期化子を提供する必要があります。

Name arr[3] { { "John", "Doe" }, { "Jane", "Smith" }, { "", "" } };

あなたのクラスshouldが「デフォルト」状態の概念を持つ理由はないので、後者は概念的に望ましいです。その場合、単にhaveを使用して、配列のすべての要素に適切な初期化子を提供します。

C++のオブジェクトが不明確な状態になることはありません。これについて考えると、すべてが非常に明確になるはずです。


代替手段はdynamicコンテナを使用することですが、これはあなたが要求したものとは異なります:

std::vector<Name> arr;
arr.reserve(3);  // morally "an uninitialized array", though it really isn't

arr.emplace_back("John", "Doe");
arr.emplace_back("Jane", "Smith");
arr.emplace_back("", "");

std::vector<Name> brr { { "ab", "cd" }, { "de", "fg" } }; // yet another way
22
Kerrek SB

Tsの配列をデフォルトで初期化するには、Tがデフォルトで構築可能でなければなりません。通常、コンパイラはデフォルトのコンストラクタを無料で提供します。ただし、コンストラクタを自分で宣言したため、コンパイラはデフォルトのコンストラクタを生成しません。

あなたのオプション:

  • 理にかなっている場合は、名前にデフォルトのコンストラクタを追加します(そうは思いませんが、問題のドメインはわかりません)。
  • 宣言時に配列のすべての要素を初期化します(nameは集約であるため、これを行うことができます);

      name someName[4] = { { "Arthur", "Dent" },
                           { "Ford", "Prefect" },
                           { "Tricia", "McMillan" },
                           { "Zaphod", "Beeblebrox" }
                         };
    
  • 使う std::vector代わりに、構築した要素のみを追加します。

オブジェクトの配列を作成するために、オブジェクトにはパラメーターを使用しないコンストラクターが必要です(たとえば、両方の文字列が空のオブジェクトのデフォルトのフォームを作成します)。これがエラーメッセージの意味です。コンパイラーは、空のオブジェクトを作成するコンストラクターを自動的に生成しますnless他のコンストラクターがあります。

空の配列要素を作成するのが理にかなっている場合(この場合、メンバーはデフォルト値、この場合は空の文字列を取得します):

-空のコンストラクターを作成します。

_class name {
  public:
    string first;
    string last;

  name() { }
  name(string a, string b){
    first = a;
    last = b;
  }
};
_

-または、必要ない場合は、既存のコンストラクタを削除します。

クラスの「空の」バージョンが意味をなさない場合、コンパイル時に配列のすべての要素に初期化パラメーターを提供する良い解決策はありません。あなたはできる:

  • とにかくコンストラクターにクラスの空のバージョンを作成させ、実際の初期化を行うinit()関数を作成させます
  • vectorを使用し、初期化時に_vector::insert_またはループを使用してオブジェクトを作成し、vectorに挿入し、コンパイル時に実行しないことを信頼します。案件。
  • オブジェクトもコピーできない場合は、オブジェクトへのスマートポインターの配列/ベクトルを使用して、初期化時にそれらを割り当てることができます。
  • C++ 11を使用できる場合は、初期化リストを使用してベクトルを初期化し、それを初期化できると思います(それがどのコンストラクタでも機能するのか、オブジェクトが別の単一の値から作成された場合のみタイプ)。例:。
_ std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
_

`

2
Jack V.

クラスのインスタンスを作成するには、 パラメーターなしのコンストラクター が必要です。現在のコンストラクタには、2つの入力文字列パラメーターが必要です。

通常、C++は、他のコンストラクターが宣言されていない場合、そのようなコンストラクター(= defaultパラメーターレスコンストラクター)を持つことを意味します。 2つのパラメーターを使用して最初のコンストラクターを宣言すると、このデフォルトの動作が上書きされ、このコンストラクターを明示的に宣言する必要があります。

作業コードは次のとおりです。

#include <iostream> 
#include <string>  // <-- you need this if you want to use string type

using namespace std; 

class name { 
  public: 
    string first; 
    string last; 

  name(string a, string b){ 
    first = a; 
    last = b; 

  }

  name ()  // <-- this is your explicit parameterless constructor
  {}

}; 

int main (int argc, const char * argv[]) 
{ 

  const int howManyNames = 3; 

  name someName[howManyNames]; 

  return 0; 
}

(ところで、コードをコンパイル可能にするために含める必要があります。)

別の方法は、宣言時にインスタンスを明示的に初期化することです

  name someName[howManyNames] = { {"Ivan", "The Terrible"}, {"Catherine", "The Great"} };
2

クラスにデフォルトのコンストラクタを追加するだけで、次のようになります。

class name {
  public:
    string first;
    string last;

  name() {
  }

  name(string a, string b){
    first = a;
    last = b;
  }
};
2
Kamyar Souri

あなたのクラス:

class name {
  public:
    string first;
    string last;

  name() { }  //Default constructor.

  name(string a, string b){
    first = a;
    last = b;
  }
};

2つの文字列パラメーターを必要とするexplicitコンストラクターがあります。コンストラクタが明示的に記述されていないクラスは、パラメータを取らないデフォルトのコンストラクタを取得します。明示的なものを追加すると、コンパイラはデフォルトのコンストラクタを生成しなくなりました。

したがって、初期化されていないオブジェクトの配列を作成する場合は、クラスにデフォルトコンストラクターを追加して、これらの2つの文字列パラメーターを指定せずにコンパイラーがそれらを作成する方法を認識できるようにします(上記のコメント行を参照)。