2017-06-29 148 views
-1

私はまだ言語にあまり慣れていませんが、現在C++で学校プロジェクトに取り組んでいます。 プロジェクト全体がいくつかのマイルストーンに分割されています。 1:さまざまなタイプのクリーチャーでリストを読み込んでベクトルに格納する 2:TGAファイルを読み込んでクラスに格納する。 ... 5:すべての読者のクリーチャー・タイプごとにTGA-Pictureを読み、それ以降の使用のために保管します。 (GUIでの印刷、削除/追加)Unique_Ptr:削除された関数を参照しようとする

だから、一度しか読み込まれないので、クラスの各タイプの画像を保存することをお勧めします。 私のTGAPictureクラスのload()関数はstd :: unique_ptrを返しますので、CreatureTypeクラスの引数として型を追加しました。だから私は、私のような類似したタイトルで約10の質問を読んで、一人一人が、あなたがunique_ptrをコピー傾けることを、指摘とstdを使用してのようなソリューションを提案::移動

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 

: はそれをやった後、私はこのようないくつかのエラーを得ました()または参照を返します。 私は自分の問題を解決するためにこれらを使用しようとしましたが、おそらく私は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; 
} 

TGAPicture:

//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(); 
    } 
} 

私はそれを動作させるために変更する必要がありますか?最適な方法は何でしょうか?私はTGA :: load()メソッドの戻り値としてunique_ptrを使用するはずです。 私はあなたがこの混乱を見ることができれば幸いです。私の英語が完璧でない場合は、私の最初の暴力ではないので、お詫びしたいと思います。

答えて

1

std::unique_ptrはコピーできません。それをコピーすることができれば、もはやユニークではありません。

あなたはコピーModelのコンストラクタでは、あなたのループ内creatureListの要素のを作成し、彼らはコピー不能メンバーを持ち、そのため、デフォルトでは自分自身をコピー不能されています。あなたが実際に要素のコピーを必要としない場合は、参照を使用する必要があります。

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の引数をオブジェクトのメンバにコピーできないことを意味します。これを修正するには2つの方法があります:CreatureListを移動するか、コピー可能にしてください。

std::unique_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(); 
    } 
} 

これは値によって、そのパラメータを取るためにModelのコンストラクタを変更し、にその値を移動させオブジェクトのcreatureListメンバー。

それは理にかなっている場合、あなたはまた、オブジェクトがpictureで指さcopys明示的なコピーコンストラクタ追加することにより、CreatureTypeコピー可能を作ることができる:

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::unique_ptrを返すようにするためにどのような理由があるように思えません:あなた自身ことを定義したいと思うので、コンパイラによって生成されます。その関数から値を返すだけであれば、これらの問題はすべて避けることができます:

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

大変申し訳ありませんが、typedef std :: vector CreatureList; あなたの深い答えをありがとう! TGAPicture :: loadPictureの戻り値の型を変更するようお勧めしますか?このようなObjectFactoryメソッドには、一意のポインターを使用する必要があります。あなたは同意するか同意しますか? – Awesome36

+0

ユニークなポインタを持つバージョンをサポートするために多くのものを変更するようです。 – Awesome36

+0

@ Awesome36あなたがする必要がある場合にのみ、ポインタで返します。実際にファクトリを実装していて、異なる具体的な型を返すことができる場合は、親型へのポインタを返さなければなりません。あなたの場合、1つの型しか返さないので、ポインタは必要ありません。オブジェクトのコピーは保存しません。返される値は最適化されるか、移動されます。 –

関連する問題