質問: d1;// _getch(); return 0; } ```
回答: オイラ一読して疑問点がどこかよくわからなかったんだけど、再読してみて Q1: 提示コード中ではコメント化している箇所 `C::operator=` を、コメント外してコンパイルするとエラーになるが、どうすればよいか? ってことであるとして以下回答。 c++,フレンドクラスの使おうとすると認識できない型です、というエラー出る。原因 で「コメント」した通りっす。 `class D` は結局のところ `C` から派生させている `class D : public C` ので、この派生クラス `D` のクラス定義は `class C` のクラス定義が完全になるまでできません。 ``` class C { ... }; // の波括弧が閉じた後でないと class D : public C { ... }; // のように C を使うことはできない ``` 当然ながら `class C { ... };` の最中にはまだ `D` は存在していないので「定義されていない識別子」のエラーが出ます。なので `D` という名前はクラス名だよ、とコンパイラに教える「クラス宣言」を先行させることで「メンバ関数宣言」はできるようになります。「クラス宣言」だけだと詳細がないので「メンバ関数の定義」はこの時点ではまだできません。 ``` // myclass.h class D; class C { ... C& operator=(const D& d); // メンバ関数宣言のみなら可能 }; ``` `class D` のクラス定義が完全になった後であれば `D` を使うことができるので「関数定義」を書くことができます。ヘッダファイル中でこの関数定義を行うと ODR に反するので `myclass.cpp` を新しく作ってその中で行う必要があります。 ``` // myclass.cpp #include "myclass.h" C& C::operator=(const D& d) { ... } ``` っていうか多分下記の解説を先にしとくべきなのかもしれない。 * 宣言 (declaration) そういう名前の変数や関数やクラスがあることをコンパイラに知らせる行為 宣言だけを行う場合、その名前を「使う」ことができる状況は限られてしまう * 定義 (definition) 変数や関数やクラスの詳細をコンパイラに知らせる行為 多くの場合、定義は同時に宣言を兼ねるが「定義にならない宣言」もある 定義が完了しないと、その名前を「使う」ことができない `class D;` ってのは「定義にならない宣言」で、これだけあるときコンパイラは - `D` ってのはクラス名であるが、その詳細は不明 - `D*` および `D&` と書いてあるコードは容認する - `extern D d;` のような「変数宣言(変数定義にならない宣言)」を容認する - `D` 自体を使うことはできない( `D` の詳細が不明なため) A1: この場合は、クラス定義内関数宣言と関数定義を分離する必要があります。関数宣言はヘッダファイルで、関数定義はソースファイルで実施のこと。 Q2-1:クラス宣言だけ先行させる使い方は普通?正しい? A2-1:普通かつ正しい行為です。関数宣言と関数定義を別に書く必要があるので1手間余計にかかりますが、オイラも何度もやったことあります。 Q2-2:基底クラスオブジェクトに、派生オブジェクトを代入する行為は普通?正しい? A2-2:オイラの経験上はそういう行為をする必然があったことが一度もないので、普通かと問われれば否。正しいかと問われれば「基底クラスが派生クラスについて事前に知っておく必要がある」ってのはまったくもって正しくない。 Q3:やっていいの? A3:実験目的、学習目的なら可。オイラの後輩君が実用に供するコードにこんなこと書いてたらリファクタリングを強制するだろう。