前提
C++のプログラム内で、ある2つの構造体A,Bを定義しました。
構造体Aではコンストラクタで構造体Bの静的メンバ関数を必要としています。一方、構造体Bでは静的メンバ変数、関数定義で構造体Aの定義を必要としています。
そういった場合、どのように実装して相互参照の状態を解消すれば良いのでしょうか。
実現したいこと
- 簡潔に構造体A,Bをエラーなく定義する。
発生している問題・エラーメッセージ
cannot convert 'A*' to 'int*'(A.hppのB::Append(this);の行) 'A' was not declared in this scope(B.hppのstatic inline std::vector<A*> As{};の行) など
該当のソースコード
C++:main.cpp
1#include <stdio.h> 2#include "A.hpp" 3#include "B.hpp" 4 5int main(){ 6 // 適当な処理 7}
C++:A.hpp
1#pragma once 2 3struct A 4{ 5 A(){ 6 B::Append(this); 7 } 8 9 void update(){ 10 // ここに更新処理 11 } 12};
C++:B.hpp
1#pragma once 2#include <vector> 3 4struct B 5{ 6 static inline std::vector<A*> As{}; 7 8 static void Append(A* a) { 9 As.push_back(a); 10 } 11 12 static void UpdateAll() { 13 for(auto& a : As){ 14 a->update(); 15 } 16 } 17};
試したこと
一応の解決策として、Aの派生クラス(Cとする)を作ることが挙げられます。
C++:A.hpp
1#pragma once 2 3struct A 4{ 5 A(){ 6 // ここにコンストラクタの処理 7 } 8 9 void update(){ 10 // ここに更新処理 11 } 12};
C++:B.hpp
1#pragma once 2#include <vector> 3#include "A.hpp" 4 5struct B 6{ 7 static inline std::vector<A*> As{}; 8 9 static void Append(A* a) { 10 As.push_back(a); 11 } 12 13 static void UpdateAll() { 14 for(auto& a : As){ 15 a->update(); 16 } 17 } 18};
C++:C.hpp
1#pragma once 2#include "A.hpp" 3#include "B.hpp" 4 5struct C : A 6{ 7 C() : A(){ 8 B::Append(this); 9 } 10};
しかし、B::Append()のためだけに派生クラスを作るのは少々簡潔ではないような気がします。
ですので、以下のような方法で解決したいと考えています。
1.仮の定義を書いてコンパイルを通す。
具体的には、A.hpp、B.hppの構造定義の前にB,Aの仮の構造体の定義を書いて、後々詳細な定義がわかるとコンパイラに伝えて解決したいと考えています。
2.構造体Bの定義文の後に、コンストラクタA()の定義をする。
具体的には、A.hpp内ではコンストラクタA()の定義をせずに(あるいは置き換え可能な仮の定義を置いて)、B.hppのBの定義が終わった後にコンストラクタA()の詳細な定義をして解決したいと考えています。
以上のようなことを行える構文、あるいは別の簡潔な構文がありましたらご教授いただけると幸いです。
補足情報(FW/ツールのバージョンなど)
エディタ:VSCode バージョン 1.72.2
コンパイラ:gcc バージョン 9.2.0
C++17(tasks.jsonのargsに"-std=c++17"を指定して実行。Aの派生クラスCを作った場合では正しく実行されました。)
ご不明な点がございましたら、お手数ですがコメントまでお知らせください。
何卒、ご教授お願いします。
回答1件
良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
2022/10/31 00:45
2022/10/31 01:42
2022/10/31 02:27