未将此指针设置为const的构造函数会导致未检测到的问题

Constructors not setting this pointer to const causes undetected issues

本文关键字:检测 问题 构造函数 设置 指针 const      更新时间:2023-10-16

将我的类裁剪到最小的可读性:

#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版本时,这段代码可能会导致一些"问题"(尽管一切运行正常)。Message的构造函数不假设this指针的const。所以即使addToFolders不是const函数,代码

Message a("hello");
Folder f;
a.save(f);
const Message b(a);

可以很好地编译。这里有一个问题,因为bconst消息,但复制构造函数将b的地址(通过addToFolders())设置为由Message*set组成的文件夹-低级const丢失。实际上,如果我要在Folder中定义一个函数来改变底层消息,我可以改变const Message bcontents,而似乎没有编译错误。

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

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

如果你在你的构造函数中使用this,这取决于你是否适当地小心-例如,你可以显式地将其const_cast转换为const *

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