延期构件施工

Deferred member construction

本文关键字:施工 构件      更新时间:2023-10-16

我有以下结构:

struct Logger::LoggerImpl {
    std::wofstream loggerStream;
}

当我创建LoggerImpl时,显然会隐式创建std::wofstream(通过编译器的默认构造函数)。

我的问题是,有没有一种方法可以在不使用指针的情况下阻止(或推迟)wofstream的构建?因为我稍后会用给定的文件名创建它。

我知道在这种情况下,这没有什么不同,但我是在理论基础上问的。

为什么不使用默认构造函数创建std::wofstream,然后只创建open()文件?绑定包含对象的生命周期似乎是正确的方法。

在C++11中,您还可以将带有构造函数的对象放入union中。当然,结果是,您需要接管union成员的终身管理。但是,通过这种方式,可以将特定成员的构造推迟到以后。请注意,在下面的代码中使用new实际上只是放置新,将对象构建到合适的位置。这里有一个例子:

#include <iostream>
#include <fstream>
#include <new>
class foo
{
    bool constructed;
    union helper {
        helper() {}
        ~helper() {}
        std::ifstream stream;
    } member;
public:
    foo(): constructed() {}
    ~foo() {
        if (constructed) {
            using std::ifstream;
            this->member.stream.~ifstream();
        }
    }
    void open(std::string const& name) {
        new (&this->member.stream) std::ifstream(name);
        constructed = true;
    }
    std::streambuf* rdbuf() {
        return this->member.stream.rdbuf();
    }
};
int main()
{
    foo f;
    f.open("foo.cpp");
    std::cout << f.rdbuf();
}

如果将"不使用指针"的定义扩展为"不必直接使用std::wofstream *",则可以:

struct Logger::LoggerImpl {
    std::shared_ptr<std::wofstream> loggerStream;

    void init () {
        loggerStream = std::make_shared<std::wofstream> ();
    }
};

我说拉伸是因为你没有直接处理std::wofstream *。这是我能想出的最好的办法。

在各种情况下推迟成员的构建非常有意义。这里有几种方法可以做到这一点;实现之间的差异是由于延迟的目的不同。

首次使用时初始化;原因:在需要之前不要浪费资源。

class Logger::LoggerImpl 
{
private:
    std::wofstream * loggerStream; // Don't expose to other classes
    std::wofstream * GetLoggerStreamImpl()
    {
        if( loggerStream == NULL )
        {
            loggerStream = new std::wofstream;
        }
        return loggerStream;
    }
public:
    LoggerImpl() : loggerStream(NULL) 
    {
    }
    std::wofstream * GetLoggerStream()
    {
        return GetLoggerStreamImpl();
    }
    void DoSomethingWithLoggerStream()
    {
        GetLoggerStreamImpl();
        // Do whatever you need with loggerStream
    }
};

通过专用方法进行初始化;原因:用于初始化的参数以前未知。

class Logger::LoggerImpl 
{
private:
    std::wofstream * loggerStream; // Don't expose to other classes
    std::wofstream * OpenLoggerStreamImpl( string filename )
    {
        if( loggerStream == NULL )
        {
            loggerStream = new std::wofstream( filename );
        }
        return loggerStream;
    }
public:
    LoggerImpl() : loggerStream(NULL) 
    {
    }
    std::wofstream * OpenLoggerStream( string filename )
    {
        return OpenLoggerStreamImpl( filename );
    }
    void DoSomethingWithLoggerStream()
    {
        if( loggerStream == NULL )
        {
            throw Exception( "Aye, Caramba! Logging stream wasn't open yet!" );
        }
        // Do whatever you need with loggerStream
    }
};