代码之家  ›  专栏  ›  技术社区  ›  Awesome36

Unique\u Ptr:尝试引用已删除的函数

  •  1
  • Awesome36  · 技术社区  · 8 年前

    所以我现在正在用C++做一个学校项目,虽然我还不太熟悉这门语言。 1: 读取包含不同类型生物的列表并将其存储在向量中 2: 读取TGA文件并将其存储在类中。

    所以我认为在类本身中存储每种类型的图片是一个好主意,因为它应该只加载一次。 TGAPicture类中的load()函数将返回std::unique\u ptr,因此我在CreatureType类中添加了该类型作为参数。

    Error   C2280   'biosim::CreatureType::CreatureType(const biosim::CreatureType &)': attempting to reference a deleted function  bio-sim-qt  E:\Development\C++\bio-sim-qt\bio-sim-qt\qtmain.cpp 58  1   
    
    Error (active)      function "biosim::CreatureType::CreatureType(const biosim::CreatureType &)" (declared implicitly) cannot be referenced -- it is a deleted function  bio-sim-qt  e:\Development\C++\bio-sim-qt\bio-sim-qt\Model.cpp  15  26  
    

    所以我读了大约10个类似标题的问题,比如我的问题,每个问题都指出,你不能复制unique\u ptr和建议的解决方案,比如使用std::move()或返回引用。 虽然我试着用这些来解决我的问题,但我一点也做不到,可能是因为我对C++非常陌生,从来没有使用过唯一的指针。

    这就是代码,似乎与我有关:

    /**
     * @class CreatureType
     * Object of the various CreatureTypes ingame
     */
    class CreatureType {
    
        private:
        std::string name;
        int strengh;
        int speed;
        int lifespan;
        std::vector<std::string> attributes;
        std::string path;
        std::unique_ptr<TGAPicture> picture; //What I tried to add in order to stre my pictures
    
        public:
        CreatureType(const std::string& name
                    , int strengh, int speed, int lifespan
                    , const std::vector<std::string>& basic_strings
                    , const std::string& path);
    
        /**
        * Initializes list with CreatureTypes by reading from a .txt-File
        */
        static CreatureList load(const std::string& file);
    
        /**
         * Printing Data in various ways
         */
        void getInfo() const;
        void getInfoInOneLine() const;
    
        std::string getName() const;
        int getStrengh() const;
        int getSpeed() const;
        int getLifespan() const;
        std::vector<std::string> getAttributes() const;
        std::string getPath() const;
    };
    

    CreatureType::CreatureType(const std::string& name
                                , int strengh, int speed, int lifespan
                                , const std::vector<std::string>& basic_strings
                                , const std::string& path)
        : name(name),
        strengh(strengh),
        speed(speed),
        lifespan(lifespan),
        attributes(basic_strings),
        path(path),
        picture(TGAPicture::loadPicture(Reference::PicturePath::creatureBasePath + path)){ }
    
    /**
     * Implementation Notes:
     * - Does a line not fullfill the requirenments, it will be ignored
     * - @see <a href="https://elearning.uni-bayreuth.de/pluginfile.php/644828/mod_resource/content/2/Aufgabenblatt_1.pdf">Formation</a>
     * - Prints data with std::cout
     */
    CreatureList CreatureType::load(const std::string& file) {
        CreatureList creatureList;
        std::ifstream fileStream; //Datei-Handle
        int lineNumber = 0;
        int correctLinesRead = 0;
    
    
        fileStream.open(file, std::ios::in);
        if (!fileStream.is_open()) {
            throw FileNotFoundException(file);
        }
    
        logger << INFO << "Einlesevorgang wird gestartet\n";
    
        //One line per loop
        while (!fileStream.eof()) {
            bool skipLine = false;
    
            std::string line;
            getline(fileStream, line);
            lineNumber++;
    
            ... //Checking if data is valid 
    
    
            //Every Parameter does exist and is valid
            creatureList.push_back(CreatureType(creatureArgs[0]
                                                , strengh, speed, lifespan
                                                , attributes, creatureArgs[5]));
            correctLinesRead++;
        }
    
    return creatureList;
    }
    

    TGA图片:

    //no padding bytes
    #pragma pack( push, 1 )
    /**
     * @struct TGAHeader
     * Represents the standard TGA-Header.
     */
    struct TGAHeader {
        char idLength;
        char colourmapType;
        char imagetype;
    
        short colourmapStart;
        short colourmapLength;
        char colourmapBits;
    
        short xOrigin;
        short yOrigin;
        short width;
        short height;
        char bits;
        char descriptor;
    
    };
    #pragma pack( pop )
    
    
    /**
    * @struct RGBA
    * Represents a Pixel with a red, green, blue and possibly alpha value
    */
    struct RGBA {
        std::uint8_t B, G, R, A;
    };
    
    /**
    * @class TGAPicture
    * Class used to represent TGA-Files, that are used in the program
    */
    class TGAPicture {
    
        public:
        TGAPicture(const TGAPicture& other)
            : pixel(other.pixel),
            header(other.header),
            width(other.width),
            height(other.height),
            size(other.size),
            bitsPerPixel(other.bitsPerPixel) {}
    
        TGAPicture(TGAPicture&& other) noexcept
            : pixel(std::move(other.pixel)),
            header(std::move(other.header)),
            width(other.width),
            height(other.height),
            size(other.size),
            bitsPerPixel(other.bitsPerPixel) {}
    
        TGAPicture& operator=(const TGAPicture& other) {
            if (this == &other)
                return *this;
            pixel = other.pixel;
            header = other.header;
            width = other.width;
            height = other.height;
            size = other.size;
            bitsPerPixel = other.bitsPerPixel;
            return *this;
        }
    
        TGAPicture& operator=(TGAPicture&& other) noexcept {
            if (this == &other)
                return *this;
            pixel = std::move(other.pixel);
            header = std::move(other.header);
            width = other.width;
            height = other.height;
            size = other.size;
            bitsPerPixel = other.bitsPerPixel;
            return *this;
        }
    
        private:
        std::vector<RGBA> pixel; //Containes every pixel of the picture
        TGAHeader header;
        short width, height, size, bitsPerPixel;
    
        ...
    
        public:
        /**
        * Loads and initializes a picture to be used in the program
        * @throws TGAExpection if file could not be loaded
        */
        static std::unique_ptr<TGAPicture> loadPicture(const std::string& path);
        TGAPicture(const std::vector<RGBA>& pixel, const TGAHeader& header);
        ~TGAPicture();
        ....
    };
    }
    #endif
    

    cpp:

    TGAPicture::TGAPicture(const std::vector<RGBA>& pixel, const TGAHeader& header)
        : pixel(pixel),
        header(header),
        width(header.width),
        height(header.height),
        size(header.width * header.height * (header.bits / 8)),
        bitsPerPixel(header.bits) { }
    
    
    
    std::unique_ptr<TGAPicture> TGAPicture::loadPicture(const std::string& path) {
        ...
    
    
        for (int i = 0; i < header.height * header.width; i++) {
            pixel[i].B = *(bufferPosition++);
            pixel[i].G = *(bufferPosition++);
            pixel[i].R = *(bufferPosition++);
            pixel[i].A = (header.bits > 24 ? *(bufferPosition++) : 0xFF);
        }
    
        /**
         * Return unique_ptr
         * - ObjectFactory
         * - Automatic Deletion
         */
        return std::unique_ptr<TGAPicture>{new TGAPicture(pixel, header)};
    
    }
    

    class Model {
    
        public:
        explicit Model(const CreatureList& creatureList);
        ~Model();
    
    
        Terrain* getTerrain() const;
        CreatureList& getCreatureList();
    
        private:
        CreatureList creatureList;
        Terrain* terrain;
    
    };
    
    
    Model::Model(const CreatureList& creatureList) : creatureList(creatureList),
                                                    terrain(new Terrain()) {
    
        for (CreatureType ty : creatureList) {  //line with errror
            ty.getInfoInOneLine();
        }
    }
    

    我希望你能看穿这场混乱,如果我的英语不完美,我想道歉,因为这不是我的第一语言。

    1 回复  |  直到 8 年前
        1
  •  5
  •   Miles Budnek    8 年前

    std::unique_ptr 不可复制。如果你能复制它,它就不再是独一无二的了。

    副本 中的元素 creatureList Model

    Model::Model(const CreatureList& creatureList)
        : creatureList(creatureList),
          terrain(new Terrain())
    {
        for (CreatureType& ty : creatureList) {  // changed to reference instead
                                                 // Note: this is still working with
                                                 //       parameter, not the object's
                                                 //       member.
            ty.getInfoInOneLine();
        }
    }
    

    实际上,您还没有提供 CreatureList ,但我怀疑它也不可复制。这意味着 Model::Model 或者让它可以复制。

    std::唯一ptr 是可移动的,这意味着 CreatureType

    Model::Model(CreatureList creatureList)  // Take by value now
        : creatureList(std::move(creatureList)),  // Move the parameter to the member
          terrain(new Terrain())
    {
        for (CreatureType& ty : this->creatureList) {  // Use this-> to access member
                                                       // instead of now moved-from
                                                       // parameter.  You could also
                                                       // just change them to have
                                                       // different names.
            ty.getInfoInOneLine();
        }
    }
    

    模型 创建者列表 成员

    通过添加显式复制构造函数来复制 picture

    CreatureType::CreatureType(const CreatureType& other)
        : name(other.name),
          strengh(other.strengh),
          speed(other.speed),
          lifespan(other.lifespan),
          attributes(other.attributes),
          path(other.path),
          picture(new TGAPicture(*other.picture))
    {
    }
    

    如果这样做,编译器将不再生成隐式移动构造函数,因此您需要自己定义它:

    CreatureType::CreatureType(CreatureType&& other)
        : name(std::move(other.name)),
          strengh(other.strengh),
          speed(other.speed),
          lifespan(other.lifespan),
          attributes(std::move(other.attributes)),
          path(std::move(other.path)),
          picture(std::move(other.picture))
    {
    }
    

    TGAPicture::loadPicture 返回 std::唯一ptr

    TGAPicture TGAPicture::loadPicture(const std::string& path) {
        // ...
        return TGAPicture{pixel, header};
    }