私はあなたがこれについて間違った方向に進んでいると思います。最初にクラスがどのように見え、どのように感じられるかを考え、次にそこで何が起こっているかを考えるべきです。コード、特にリストのようなものを処理するコードをクラスに入れることを検討している場合、最初に、クラスがサポートする必要がある操作 (追加、消去、検索?、インデックス?) の精神的なリストを作成します。次に、クラスに持たせたいインターフェイスについて考え始めます。次に、コードをクラスに入れるのは通常、小さなステップです。これは、そのほとんどが前の 2 つのステップですでに決定されているためです。
あなたのコードを見ると、戻り値はnext
再帰呼び出しの後に前の要素のポインターをリセットするためにのみ使用されていることがわかります。したがって、関数をリストのユーザー用と内部のみで使用する関数に分けることができます。これは重要なポイントです。これは、クラスのインターフェースが、クラスのユーザー用のものを外部 (「パブリック」) に表示するだけでよいことを意味するためです。内部で行うことは、独自のビジネスです。これにより、クラスのユーザーを邪魔することなく、これを再帰から反復 (より効率的) に変更できます。
さて、あなたの場合、クラスに入れたいリストがあります。アドレスで要素を指定するリストから要素を削除できます。これは要素を破壊しませんが、それを呼び出し元に任せます (生のポインターは常に所有権の質問をしますが、それは別の問題です)。リストを埋める方法やノードを割り当てる方法など、他のことはまだ不明です。これにより、消去操作で次のユースケースが得られます。
List l;
... // fill l
Node* n = ... // some node
l.erase(n);
delete n;
リスト型の場合、これは次のようになります。
struct List
{
void erase(Node* n)
{
m_head = doErase(m_head, n);
}
private:
static Node* doErase(Node* head, Node* node)
{
... // your function here
}
Node* m_head;
};
まだいくつか不足していることに注意してください。特に、クラスをコピー不可にしたい場合や、ノードが null の場合 (例: assert(n);
in erase()
) またはリストにない場合 ( throw invalid_argument("node not element of list");
in do_erase()
) にどうするかを決定する必要があります。ただし、これで開始できることを願っています。