1

クラスの作成に関しては、パブリック データ メンバーはないと言われたことがあります。それは問題ありません。理由は理解していますが、ここに私の問題があります。クラスで使用している構造体があります (線形リンク リスト)。構造体フィールド (配列) の 1 つを NULL に初期化して、クライアントがガベージ値でいっぱいの初期化されていない構造体ではなく、有効な構造体を渡していることを確認できるようにしたいと思います。C++ では構造体宣言にデフォルト値を設定できないことがわかりました。では、クライアントからガベージを受け取るのを防ぐにはどうすればよいでしょうか?

struct task {
    char *description;
    char *name;
    float time_remaining;
    float time_spent;
};

それから私のクラスでは、次のようなことをしようとしています:

//I am making a copy of "to_add" and storing it in the LLL
int list::add_to_list(const task & to_add)
{ /.../ }

ユーザーが初期化されていない「タスク」をリンクされたリストに追加したくありません...どうすればよいですか? その構造体をクラスに変換し、データ メンバーをプライベートに移動したとき、データ メンバーにアクセスしてそれらのコピーを作成しようとすると、大量の問題が発生しました。var の値に影響を与えるようなことをしないように細心の注意を払いましたが、コンパイラから逃れることができず、「エラー: 'const task' を 'char* task::get_comp_name の 'this' 引数として渡しています」というエラーが表示されました。 ()' は修飾子を破棄します [-fpermissive]" ("get_comp_name") は、値を編集しておらず、コピーを渡すだけだと確信していたゲッターの 1 つでした) 自分を撃つ前に助けてください。顔に(表情に。

4

3 に答える 3

4

C++ では、astructと aclassはアクセス制御を除いて同じです。したがって、構造体のメンバーと継承へのデフォルトのアクセスはパブリックですが、クラスのアクセスはプライベートです。したがって、構造体にデフォルトのコンストラクターと他のコンストラクターを与えて初期化することができます。

struct task {
    task() : desctiption(0), name(0), time_remaining(0.), time_spent(0.) {}
    char *description;
    char *name;
    float time_remaining;
    float time_spent;
};

コンストラクターを追加することの副作用の 1 つは、構造体が集合体ではなくなることです。これはあなたにとって問題になる場合とそうでない場合があります。

C++11 では、宣言の時点でメンバーを初期化することもできます。

struct task {
    char *description{nullptr};
    char *name{nullptr};
    float time_remaining{0};
    float time_spent{0};
};

このインプレース初期化はtype x = y構文も受け入れ、引数のない{}初期化は値の初期化の結果になり、プリミティブ型の初期化はゼロになるため、例の引数は省略できます

于 2012-04-20T05:38:38.240 に答える
2

ここにはいくつかの問題があります。

公開または非公開?

パブリック属性は便利に思えるかもしれませんが、通常、予期しないときに戻ってきて噛み付きます。私はすでにとの問題を疑っていtime_remainingますtime_spent:私は両方がまったく同時に変更されていると思いますね?

デフォルトでは、変数属性はである必要がありますprivate。これにより、クラスは、タスクの存続期間を通じて定数などの不変条件を適用できます。time_remaining + time_spent

定数属性がであるのは問題ありませpublicん。不変条件でのそれらの役割は、とにかくコンストラクターで一度だけ解決されます。

しかし、奇妙なエラーメッセージ?

これは、優れたチュートリアルや本が不足しているためです。手元にある問題は非常に単純です。それはconst-ness関連の問題です。

オブジェクトは、constconst-referenceまたはvalueによってのみ関数/メソッドに渡され、メソッドのみconstが呼び出されます。あなたの場合、メソッドの適切な宣言には、メソッド名の後に修飾子をname()付ける必要があります。const

まとめて

std::stringそして、操作がとても簡単なので、投げ込みます。

class Task {
public:
    Task(): time_remaining(0), time_spent(0) {}
    Task(std::string name, std::string desc, float duration):
        _name(name), _desc(desc), _time_remaining(duration), _time_spent(0) {}

    // Accessors
    std::string const& name() const { return _name; }
    std::string const& description() const { return _desc; }
    float time_remaining() const { return _time_remaining; }
    float time_spent() const { return _time_spent; }

    // Modifiers
    void spend(float duration) {
        _time_remaining -= duration;
        _time_spent += duration;
    }

private:
    std::string _name, _desc;
    float _time_remaining, _time_spent;
}; // class Task

注:メソッドにduration渡されたものが属性spendよりも優れていないことを確認することはおそらく有益である可能性があり_time_remainingます。そうでない場合は、持っているよりも多くを費やします...

于 2012-04-20T07:51:56.667 に答える
1

構造体のコンストラクターを実装します。

struct task {
    task() : description(0), name(0), time_remaining(0), time_spent(0) {}
    char *description;
    char *name;
    float time_remaining;
    float time_spent;
};

C++ のクラスと構造体の唯一の違いは、そのメンバーの既定のアクセシビリティです。

于 2012-04-20T05:37:28.043 に答える