未将此指针设置为 const 的构造函数会导致未检测到的问题
Constructors not setting this pointer to const causes undetected issues
将我的 类 削减到最低限度以便于阅读:
#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;
}
在定义 messages
的 const
版本时,此代码可能会导致一些 "problems"(尽管一切正常)。 Message
的构造函数不假定 this
指针的 const
。因此,即使 addToFolders
是一个非 const
函数,代码
Message a("hello");
Folder f;
a.save(f);
const Message b(a);
可以正常编译。这里有一个问题,因为 b
是一条 const
消息,但是复制构造函数将 b
的地址(通过 addToFolders()
)设置为包含 [=24] 的文件夹=] of Message*
- 低级 const
丢失。事实上,如果我然后在 Folder
中定义一个函数,它改变了底层消息,我可以改变 const Message b
的 contents
似乎没有编译错误。
一个解决方案是将 Folder
的设置更改为 set<const message*>
,但这不允许我通过文件夹更改消息(我确实希望这样做)。我如何防止 message
的 const 对象被创建,或者更好的是,强制构造函数中的 this
指针为 const
以便 addToFolders()
失败?
您无法阻止 const
个正在构建的实例。
如果您在构造函数中使用 this
,则您需要适当小心 - 例如,您可以将其显式 const_cast
为 const *
。
一般来说,如果对象的管理不在对象自己的范围内处理,效果会更好 class。例如,您可以限制对象只能通过 folder
创建,然后 folder
可以确保它被正确处理。 (这实际上只是关注点分离的一个例子。)
将我的 类 削减到最低限度以便于阅读:
#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;
}
在定义 messages
的 const
版本时,此代码可能会导致一些 "problems"(尽管一切正常)。 Message
的构造函数不假定 this
指针的 const
。因此,即使 addToFolders
是一个非 const
函数,代码
Message a("hello");
Folder f;
a.save(f);
const Message b(a);
可以正常编译。这里有一个问题,因为 b
是一条 const
消息,但是复制构造函数将 b
的地址(通过 addToFolders()
)设置为包含 [=24] 的文件夹=] of Message*
- 低级 const
丢失。事实上,如果我然后在 Folder
中定义一个函数,它改变了底层消息,我可以改变 const Message b
的 contents
似乎没有编译错误。
一个解决方案是将 Folder
的设置更改为 set<const message*>
,但这不允许我通过文件夹更改消息(我确实希望这样做)。我如何防止 message
的 const 对象被创建,或者更好的是,强制构造函数中的 this
指针为 const
以便 addToFolders()
失败?
您无法阻止 const
个正在构建的实例。
如果您在构造函数中使用 this
,则您需要适当小心 - 例如,您可以将其显式 const_cast
为 const *
。
一般来说,如果对象的管理不在对象自己的范围内处理,效果会更好 class。例如,您可以限制对象只能通过 folder
创建,然后 folder
可以确保它被正确处理。 (这实际上只是关注点分离的一个例子。)