我确实事先在这里找到了一个确切的问题,但是我没有相同的原因(或者至少我是这样认为的)。我的AnimatedSprite类具有Timer成员,该成员被制成不可复制的(明确删除了copy ctor和operator =)。但是,当我尝试在其他类的ctor中初始化sprite时,却收到一条错误消息,指出我正在引用已删除的copy operator =。

Timer.h:

#pragma once
#include <set>

class Timer
{
public:
    Timer() :
        currentTime_{0},
        expirationTime_{0}
    {}
    Timer(unsigned expirationTime) :
        currentTime_{ expirationTime },
        expirationTime_{ expirationTime }
    {
        timers_.insert(this);
    }

    ~Timer() {
        timers_.erase(this);
    }
    // Here
    Timer(const Timer& other) = delete;
    Timer& operator=(const Timer& other) = delete;

    Timer(Timer&& other) = default;
    Timer& operator=(Timer&& other) = default;


    //   Assumes the user knows if |this| is active or not
    unsigned currentTime() const { return currentTime_; }

    bool active() const { return currentTime_ < expirationTime_; }
    bool expired() const { return !active(); }
    void reset() { currentTime_ = 0; }
    void disable() { currentTime_ = expirationTime_; }


    static void updateAll(unsigned elapsedTime);

private:

    void update(unsigned elapsedTime) {
        if (active()) {
            currentTime_ += elapsedTime;
        }
    }


    static std::set<Timer*> timers_;
    unsigned currentTime_;
    const unsigned expirationTime_;

};

AnimatedSprite.h
#pragma once
#include <vector>
#include <map>
#include "Globals.h"
#include "Sprite.h"
#include "Timer.h"


class Sprite;
class Graphics;

class AnimatedSprite : public Sprite
{
public:
    AnimatedSprite() = default;
    AnimatedSprite(Graphics& graphics, const std::string& filePath,
        int sourceX, int sourceY, int width, int height,
        unsigned frameLength, unsigned frameCount);

    void update(bool once = false);
    const bool completedOnce() const { return once_; }

private:

    Timer frameTimer_;
    unsigned currentFrame_{ 0 };
    unsigned totalFrames_;
    bool once_{ false };    //  if true, plays animation once
};

然后我这样做:
sprite_ = AnimatedSprite( graphics, "Resource/NpcSym.png", 0, 1, 16, 16, 50, 5 );

难道不应该在这里叫移动运算符(operator)吗?我的RHS是否不在右值上方的行中?

最佳答案

有关您的AnimatedSprite的某些信息,它无法移动。一旦消除,它将尝试复制。而您得到您的错误。
Sprite中的某些内容可能阻止它被移动。或Timer中的内容;如果您无法移动东西,=default可以变成=delete

我使用的一种技术是注入(inject)有关此类假设的静态断言。

static_assert( std::is_move_assignable<Sprite>{}, "Cannot move Sprite" );
static_assert( std::is_move_constructible<Sprite>{}, "Cannot move Sprite" );
static_assert( std::is_move_assignable<Timer>{}, "Cannot move Timer" );
static_assert( std::is_move_constructible<Timer>{}, "Cannot move Timer" );

现在,使用我的大脑编译器,我可以看到:
const unsigned expirationTime_;

将阻止Timer上的移动分配。

备份设计:
sprite_ = AnimatedSprite( graphics, "Resource/NpcSym.png", 0, 1, 16, 16, 50, 5 );

将一个当前正在制作动画的精灵分配给另一个精灵是否有意义?

我对此表示怀疑。

我会=delete operator=(&&)

sprite_替换为std::optional<AnimatedSprite>,然后执行以下操作:
sprite_.emplace( graphics, "Resource/NpcSym.png", 0, 1, 16, 16, 50, 5 );

这通常比拥有“处于非精灵状态的精灵”更为理智。

09-05 16:10