2013-12-09 2 views
1

Я пытаюсь передать пользовательский объект (TextureInfos) через многократные функции.C++ возвращающий объект класса через множественную функцию

Вызов:

TextureManager::Instance()->getTextureInfos("TEST",0) 

TextureManager.cpp

TextureInfos& TextureManager::getTextureInfos(std::string key, int id) 
{ 
    TextureSet textureSet = textureSets[key]; 

    return textureSet.getTextureInfos(id); 
} 

TextureSet .cpp

TextureInfos& TextureSet::getTextureInfos(int id) 
{ 
    sf::Texture texture; 
    sf::IntRect rect; 

    if (id < tileCount) { 
     int x = (id % maxCol) * tileWidth; 
     int y = (id/maxCol) * tileHeight; 
     rect.left = x; 
     rect.top = y; 
     rect.width = tileWidth; 
     rect.height = tileHeight; 
    } 

    TextureInfos *textureInfos = new TextureInfos(texture,rect); 

    return textureInfos; 
} 

Я новичок в C++, и я думаю, что я пропустил что-то с оператором «&» и «*» и т. Д. Поскольку этот код не работает на данный момент ...

Любая помощь? Большое спасибо.

EDIT:

Ok поэтому цель этого кода, чтобы получить TextureInfos объект в конце процесса. Для этого мне нужно вызвать метод getTextureInfos из TextureManager, который также вызывает getTextureInfos от TextureSet.

Вот полный код TextureManager.cpp

#include "TextureManager.h" 
#include <iostream> 
#include <fstream> 

TextureManager TextureManager::m_TextureManager; 
const std::string basePath="Assets/Graphics"; 

#pragma region Constructor 
TextureManager::TextureManager() 
{ 
    textureSets.clear(); 
} 

TextureManager::~TextureManager() 
{ 

} 
#pragma endregion 

#pragma region Textures management 

// Charge un set de texture a partir d'un nom de fichier 
void TextureManager::LoadTextureset(std::string fileName,std::string key) { 

    TextureSet textureSet; 
    textureSet.init(basePath + fileName, key); 

    textureSets[key] = textureSet; 
} 

// Récupère une texture de la liste 
TextureInfos TextureManager::getTextureInfos(std::string key, int id) 
{ 
    TextureSet textureSet = textureSets[key]; 

    return textureSet.getTextureInfos(id); // HERE I GET AN ERROR 
} 

#pragma endregion 

линия, которая комментируется в конце, где я получил ошибку:

no suitable user-defined conversion from "TextureInfos" to "TextureInfos" exists. 

И для TextureSet.cpp:

#include "TextureSet.h" 
#include <iostream> 
#include <fstream> 
#include "RapidXML\rapidxml.hpp" 
#include "Debug.h" 

const std::string basePath="Assets/Graphics"; 

using namespace rapidxml; 

#pragma region Constructor 
TextureSet::TextureSet() 
{ 

} 

TextureSet::~TextureSet() 
{ 

} 
#pragma endregion 

void TextureSet::init(std::string l_filePath,std::string l_key) 
{ 
    filePath = l_filePath; 
    key = l_key; 

    // On détermine les URLs des fichiers 
    std::string setDescriptorPath = filePath + ".xml"; 
    std::string setTilesetPath = filePath + ".png"; 

    // On charge la texture 
    if (!textureSet.loadFromFile(setTilesetPath)) 
     throw "ça load pas"; 

    // On lis le xml 
    std::ifstream xmlDescriptor(setDescriptorPath); 
    if(!xmlDescriptor) 
     throw "Could not load tileset: " + setDescriptorPath; 

    std::string xmlDescriptorContents; 
    { 
     std::string line; 
     while(std::getline(xmlDescriptor, line)) 
      xmlDescriptorContents += line; 
    } 

    std::vector<char> xmlData = std::vector<char>(xmlDescriptorContents.begin(), xmlDescriptorContents.end()); 
    xmlData.push_back('\0'); 

    //Create a parsed document with &xmlData[0] which is the char* 
    xml_document<> doc; 
    doc.parse<parse_no_data_nodes>(&xmlData[0]); 

    //Get the root node 
    xml_node<>* root = doc.first_node(); 
    xml_node<>* imagefile = root->first_node("params"); 

    maxRow = atoi(imagefile->first_attribute("maxRow")->value()); 
    maxCol = atoi(imagefile->first_attribute("maxCol")->value()); 
    tileWidth = atoi(imagefile->first_attribute("tileWidth")->value()); 
    tileHeight = atoi(imagefile->first_attribute("tileHeight")->value()); 
    tileCount = atoi(imagefile->first_attribute("tileCount")->value()); 
} 

TextureInfos TextureSet::getTextureInfos(int id) 
{ 
    sf::Texture texture; 
    sf::IntRect rect; 

    if (id < tileCount) { 
     int x = (id % maxCol) * tileWidth; 
     int y = (id/maxCol) * tileHeight; 
     rect.left = x; 
     rect.top = y; 
     rect.width = tileWidth; 
     rect.height = tileHeight; 
    } 

    TextureInfos textureInfos(texture,rect); 

    return textureInfos; 
} 

TextureInfos.h

#include <unordered_map> 
#include <vector> 
#include <SFML\Graphics.hpp> 
#include <string> 

class TextureInfos 
{ 

private: 

protected: 

public: 
    TextureInfos(sf::Texture& l_texture, sf::IntRect l_textureRect); 
    ~TextureInfos(); 

    sf::Texture& texture; 
    sf::IntRect textureRect; 
}; 

ответ

1

Нет, это не работает, потому что оно даже не компилируется. Причина, по которой он не компилируется, заключается в том, что вы пытаетесь вернуть указатель в качестве ссылки. Указатель и ссылка - две разные вещи.

Для быстрого, простого и грязного исправления измените типы возврата от TextureInfos& до TextureInfos*.


Быстрое исправление Изложенное выше «грязный», потому что, как вы используете код, который вы будете иметь утечку памяти (вы выделяете память с new но не освобождаете его).

Это можно решить двумя способами: либо вернуть по значению вместо использования указателей/ссылок. Или используйте интеллектуальные указатели, такие как std::unique_ptr.

+0

Спасибо за ваши объяснения. Значение «по значению» означает передать объект класса в параметрах функции, например ссылку? – ApheX

+0

@ApheX Нет, просто верните его без указателей или ссылок, поэтому возвращайте тип как простой «TextureInfos», а затем объявите переменную как простой «textureInfos», а не указатель. –

+0

Спасибо, я использую простой объект вместо указателя. Но при этом я получил еще одну ошибку. Я редактировал свой вопрос. – ApheX

0

Согласно вашему названию объекта, я предполагаю, что вы хотите иметь набор объектов в вашем TextureSet. Поэтому я предлагаю добавить в свой объект приватную переменную и протестировать новые запросы на получение этого объекта. Затем вы можете безопасно вернуть ссылку на участника.

1

Если вы можете избежать использования динамического распределения памяти только отредактировать TextureSet::getTextureInfos вернуть новый объект стека по значению (обратите внимание, что будет возвращать значение оптимизации, если вы беспокоитесь об эффективности):

TextureInfos TextureSet::getTextureInfos(int id) 
{ 
    // ... 
    return TextureInfos(texture, rect); 
} 

в противном случае, если вам действительно нужно динамическое выделение, используйте std::shared_ptr, чтобы избежать утечек памяти:

std::shared_ptr<TextureInfos> TextureSet::getTextureInfos(int id) 
{ 
    // ... 
    return std::make_shared<TextureInfos>(texture, rect); 
} 
+0

Спасибо, Джеффри! Я не знал об этом трюке выделения памяти. Но я все еще получаю сообщение об ошибке в TextureManager, как объясняется в моем редактировании исходного вопроса. – ApheX

0

думать, что выглядит очень тревожным является то, что TextureInfos держит ссылку на текстуру, и вы строите ее из пройденной ссылки.

TextureInfos(sf::Texture& l_texture, sf::IntRect l_textureRect); 

sf::Texture& texture; 
sf::IntRect textureRect; 

Предполагая, что конструктор делает что-то вроде этого

TextureInfos(sf::Texture& l_texture, sf::IntRect l_textureRect) : 
    texture(l_texture), 
    textureRect(l_textureRect) 
{ 
} 

... то вы входите в мир много боли. Посмотрите на GetTextureInfos(), чтобы понять, почему: -

TextureInfos& TextureSet::getTextureInfos(int id) 
{ 
    sf::Texture texture; 
    sf::IntRect rect; 

    ... 

    TextureInfos *textureInfos = new TextureInfos(texture,rect); 

    return textureInfos; 
} 

Игнорируя очевидный вопрос, что это, скорее всего, утечка возвращаемый объект, то есть главная проблема, что возвращаемый объект содержит ссылку на texture - но texture вышел сфера действия больше недействительна!

Я не могу предложить простое решение, но вам нужно убедиться, что вы понимаете вопросы управления жизненным циклом и прав собственности на объекты, которые вы создаете. Умные указатели (и возвращение целых объектов, а не ссылок) обычно являются ключевыми частями этого.

Смежные вопросы