4

私はJavaのバックグラウンドを持っていますが、その後C ++を学び、数年前からプログラミングを行っています(プログラムを最初から設計するのではなく、ほとんどの場合、デバッグと修正の作成を行っています)。しかし、今日私は問題に遭遇しました、そして率直に言って、私はそれに遭遇するのにこれほど長い時間がかかったことに少し驚いています。

Class1という名前のクラスがあり、そのヘッダーファイルに(他のコードの中でも)次のものが含まれているとします。

class Class1 {
    private:
        Class2 object;
}

Class2クラスには、デフォルトのコンストラクターが指定されていません。ここで、Class1コンストラクターで、ファイルのバイナリヘッダーを読み取り、そこから解析した情報を使用して、以下の擬似コードに示すように、Class2を初期化します。

Class1::Class1(std::string) {
    // Read some binary info from a file here

    // Parse that binary info

    object2 = Class2(info);

Javaでは、RAIIパラダイムを使用していないため、これは完全に合法です。ただし、C ++はRAIIを使用するため、オブジェクト2は、私が行うまでにデフォルトのコンストラクターで既に初期化されていますobject2 = Class2(info);。作成する必要のある情報がobjectまだなかったため、元々(Class1ヘッダーファイルで)そのコンストラクターを呼び出すことはできませんでした。object2ただし、コンストラクターを表示/使用するには他の関数が必要なため、コンストラクターに対してローカルにすることはできません。

明らかにこれは機能しません。このようなものの標準的なアプローチは何ですか?私は実際に、Class1を次のようなClass2ポインタを持つように変更することを考えました。

class Class1 {
    private:
        Class2* objectPointer;
}

その後、を呼び出し*objectPointer = Class2(info)ます。ただし、私の場合の「Class2」はifstreamであり、operator=関数が削除されているようで、どちらのアプローチでも機能しません。

だから...どうすればこれを行うことができますか?

4

4 に答える 4

6

あなたobjectはそうではないのでconst、それはすべて完全に合法です。ただし、objects初期化フェーズで初期化する場合は、情報を提供する必要があります。あなたはそのようなことをすることができます

 Class1::Class1(std::string file_name) : object(InfoFromFile(file_name)) {}

ここでInfoFromFile()、スタンドアロン関数(.ccファイル内の匿名名前空間で宣言されている)またはの静的メンバー関数のいずれかになりますClass1。に必要な情報を生成するためにfile_nameよりも多くの情報が必要な場合はClass2、その関数に提供できます。

于 2012-09-13T17:06:33.150 に答える
5

「読み取りと解析」の部分でオブジェクトを作成する必要がない場合は、それを静的(または非メンバー)関数に移動し、その結果を使用してメンバーを初期化できます。

Class1::Class1(std::string) :
    object2(read_class2_info(some_file))
{}

何らかの理由でファイルの読み取りをオブジェクトの構築から実際に分離できず、object2後で再割り当てできない場合は、ポインターを使用する必要があります。オブジェクトを作成するには、次を使用しますnew

objectPointer = new Class2(info);

ただし、三つのルールをいじくりまわす必要がないようにするには、動的オブジェクトを自分で管理することを避け、代わりにスマートポインターを使用する必要があります。

std::unique_ptr<Class2> objectPointer;

objectPointer.reset(new Class2(info));
于 2012-09-13T17:05:56.507 に答える
2

ローカル関数を使用して、バイナリ情報を読み取り、コンストラクター リストで直接初期化するビットを実行することをお勧めします。

namespace {

InfoObject readInfo(std::string s)
{
// Read some binary info from a file here

// Parse that binary info
  return info;
}

}

Class1::Class1(std::string s)
: object(readInfo(s))
{
}

もちろん、ポインタを使用することもオプションです。これが、これが Java でより自然に機能する理由でもあります (すべてのユーザー型は内部的にポインターです)。ただし、おそらくスマートポインターを使用したいと思うでしょう。

于 2012-09-13T17:05:37.100 に答える
1

objectダミーデータで初期化し、解析したら新しいデータで更新する必要があると思います。

このようなもの:

Class1(std::string str)
 : object("some valid-but-meaningless data")
{
    // parse info
    object = Class2(info);

これが適切でない場合は、静的ファクターメソッドで解析を実行する必要があります。このメソッドは、コンストラクターに情報を渡します(これはプライベートにすることもできます)。このようなもの:

Class1(Info info)
 : object(info)
{
    // whatever else you want
}

static Class1 create(std::string)
{
    // parse info
    return Class1(info);
}

編集:私は実際にウォルターの答えがより好きです。初期化で関数を使用することをお勧めします。私はあなたが考えることができるいくつかの代替案のためにこれをここに残しています。

于 2012-09-13T17:06:44.287 に答える