为了便于阅读,我将课程简化为最低限度:
#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()
)设置为由{{1}组成的文件夹} set
- 低级别Message*
丢失了。实际上,如果我要在const
中定义一个更改底层消息的函数,我可以更改const消息Folder
的{{1}},看似没有编译错误。
解决方案是将contents
的设置更改为b
,但这不允许我通过文件夹(我实际需要)更改邮件。我如何防止创建Folder
的const对象,或者甚至更好地强制构造函数中的set<const message*>
指针为message
,以便this
失败?
答案 0 :(得分:2)
您无法阻止构建const
个实例。
如果您在构造函数中使用this
,则需要特别小心 - 例如,您可以const_cast
明确const *
。
通常,如果对象的管理未在对象自己的类中处理,则效果会更好。例如,您可以限制事物,以便只能通过folder
创建对象,然后folder
可以确保正确处理对象。 (这实际上只是关注点分离的一个例子。)