読みやすくするために、クラスを最小限にカットします。
#ifndef MESSAGEFOLDER
#define MESSAGEFOLDER
#include <string>
#include <set>
class Message;
class Folder{
public:
void addMsg(Message* m) { messages.insert(m); }
~Folder() { removeFromMessages(); }
private:
std::set<Message*> messages;
void removeFromMessages(); //removes its pointers from Messages
};
class Message{
friend class Folder;
public:
Message(const std::string &s = ""): contents(s) { }
Message(const Message& rhs): contents(rhs.contents), folders(rhs.folders) { addToFolders(); }
Message& save(Folder&);
~Message() { removeFromFolders(); }
private:
std::string contents;
std::set<Folder*> folders;
void addToFolders();
void removeFromFolders(); //removes its pointers from Folders
};
#endif // MESSAGEFOLDER
MessageFolder.cpp 内
void Message::addToFolders(){
for(const auto& f : folders)
f->addMsg(this);
}
Message& Message::save(Folder& f){
folders.insert(&f);
f.addMsg(this);
return *this;
}
このコードはconst、messages. のコンストラクターは、ポインターMessageを想定していません。したがって、コードは関数ではありませんがconstthisaddToFoldersconst
Message a("hello");
Folder f;
a.save(f);
const Message b(a);
正常にコンパイルされます。bはconstメッセージですが、コピー コンストラクターはbのアドレスを ( を介してaddToFolders()) から構成されるフォルダーにset設定するため、ここに問題があります。Message*低レベルconstが失われます。Folder実際、基になるメッセージを変更する関数を定義すると、コンパイル エラーなしでcontentsconst メッセージを変更できます。b
解決策は、Folderの設定をset<const message*>に変更することですが、これにより、フォルダーを介してメッセージを変更できなくなります (これは実際に望んでいます)。const オブジェクトが作成されるのを防ぐにはどうすればmessageよいですか? あるいは、thisコンストラクター内のポインターが失敗するconstように強制するにはどうすればよいでしょうか?addToFolders()