読みやすくするために、クラスを最小限にカットします。
#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
を想定していません。したがって、コードは関数ではありませんがconst
this
addToFolders
const
Message a("hello");
Folder f;
a.save(f);
const Message b(a);
正常にコンパイルされます。b
はconst
メッセージですが、コピー コンストラクターはb
のアドレスを ( を介してaddToFolders()
) から構成されるフォルダーにset
設定するため、ここに問題があります。Message*
低レベルconst
が失われます。Folder
実際、基になるメッセージを変更する関数を定義すると、コンパイル エラーなしでcontents
const メッセージを変更できます。b
解決策は、Folder
の設定をset<const message*>
に変更することですが、これにより、フォルダーを介してメッセージを変更できなくなります (これは実際に望んでいます)。const オブジェクトが作成されるのを防ぐにはどうすればmessage
よいですか? あるいは、this
コンストラクター内のポインターが失敗するconst
ように強制するにはどうすればよいでしょうか?addToFolders()