繁体   English   中英

使用std :: unique_ptr的C ++ Pimpl Idiom Incomplete Type

[英]C++ Pimpl Idiom Incomplete Type using std::unique_ptr

我为证明问题所需的大量代码道歉。 我在使用带有std :: unique_ptr的pimpl习惯用法时遇到了问题。 具体地说,当一个类(具有pimpl'ed实现)被用作具有pimpl'ed实现的另一个复合类中的成员数据时,似乎会出现问题。

我能够找到的大部分答案都是缺少明确的析构函数声明 ,但正如你在这里看到的,我已经声明并定义了析构函数。

这段代码有什么问题,可以修改它来编译而不改变设计吗?

注意:错误似乎发生在SomeComposite :: getValue()的定义中,并且编译器在编译时才能看到错误。 在memory.h中遇到错误,消息是'sizeof'的无效应用程序到不完整类型'pimplproblem :: SomeInt :: impl'

SomeInt.h

#pragma once
#include <iostream>
#include <memory>

namespace pimplproblem
{
    class SomeInt
    {

    public:
        explicit SomeInt( int value );
        SomeInt( const SomeInt& other ); // copy
        SomeInt( SomeInt&& other ) = default; // move
        virtual ~SomeInt();
        SomeInt& operator=( const SomeInt& other ); // assign
        SomeInt& operator=( SomeInt&& other ) = default; // move assign
        int getValue() const;

    private:
        class impl;
        std::unique_ptr<impl> myImpl;
    };
}

SomeInt.cpp

#include "SomeInt.h"

namespace pimplproblem
{
    class SomeInt::impl
    {
    public:
        impl( int value )
        :myValue( value )
        {}

        int getValue() const
        {
            return myValue;
        }
    private:
        int myValue;
    };

    SomeInt::SomeInt( int value )
    :myImpl( new impl( value ) )
    {}

    SomeInt::SomeInt( const SomeInt& other )
    :myImpl( new impl( other.getValue() ) )
    {}

    SomeInt::~SomeInt()
    {}

    SomeInt& SomeInt::operator=( const SomeInt& other )
    {
        myImpl = std::unique_ptr<impl>( new impl( other.getValue() ) );
        return *this;
    }

    int SomeInt::getValue() const
    {
        return myImpl->getValue();
    }
}

SomeComposite.h

#pragma once
#include <iostream>
#include <memory>
#include "SomeInt.h"

namespace pimplproblem
{
    class SomeComposite
    {   

    public:
        explicit SomeComposite( const SomeInt& value );
        SomeComposite( const SomeComposite& other ); // copy
        SomeComposite( SomeComposite&& other ) = default; // move
        virtual ~SomeComposite();
        SomeComposite& operator=( const SomeComposite& other ); // assign
        SomeComposite& operator=( SomeComposite&& other ) = default; // move assign
        SomeInt getValue() const;

    private:
        class impl;
        std::unique_ptr<impl> myImpl;
    };
}

SomeComposite.cpp

#include "SomeComposite.h"

namespace pimplproblem
{
    class SomeComposite::impl
    {
    public:
        impl( const SomeInt& value )
        :myValue( value )
        {}

        SomeInt getValue() const
        {
            return myValue;
        }
    private:
        SomeInt myValue;
    };

    SomeComposite::SomeComposite( const SomeInt& value )
    :myImpl( new impl( value ) )
    {}

    SomeComposite::SomeComposite( const SomeComposite& other )
    :myImpl( new impl( other.getValue() ) )
    {}

    SomeComposite::~SomeComposite()
    {}

    SomeComposite& SomeComposite::operator=( const SomeComposite& other )
    {
        myImpl = std::unique_ptr<impl>( new impl( other.getValue() ) );
        return *this;
    }

    SomeInt SomeComposite::getValue() const
    {
        return myImpl->getValue();
    }
} 

你不能使用带有Pimpl类的头文件中声明的默认构造函数和赋值运算符(例如SomeInt( SomeInt&& other ) = default; ),因为默认实现是内联的,并且在声明SomeInt的声明SomeInt::impl不完整,所以unique_ptr抱怨。 您必须自己声明和定义所有特殊成员函数(例如,在实现文件中)。

也就是说,更改SomeIntSomeComposite声明如下:

// SomeInt.h
SomeInt( SomeInt&& other ); // move
SomeInt& operator=( SomeInt&& other ); // move assign

// SomeInt.cpp
// after definition of SomeInt::impl
SomeInt::SomeInt( SomeInt&& other ) = default;
SomeInt& operator=( SomeInt&& other ) = default;

另一个选择是创建自己的Pimpl指针,如本答案中所示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM