未将此指针设置为 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;
}

在定义 messagesconst 版本时,此代码可能会导致一些 "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 bcontents 似乎没有编译错误。

一个解决方案是将 Folder 的设置更改为 set<const message*>,但这不允许我通过文件夹更改消息(我确实希望这样做)。我如何防止 message 的 const 对象被创建,或者更好的是,强制构造函数中的 this 指针为 const 以便 addToFolders() 失败?

您无法阻止 const 个正在构建的实例。

如果您在构造函数中使用 this,则您需要适当小心 - 例如,您可以将其显式 const_castconst *

一般来说,如果对象的管理不在对象自己的范围内处理,效果会更好 class。例如,您可以限制对象只能通过 folder 创建,然后 folder 可以确保它被正确处理。 (这实际上只是关注点分离的一个例子。)