[英]C++ returning class object through multiple function
我试图通过多个函数传递自定义对象( TextureInfos
)。
电话是:
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 ++的新手,我想我想念一下运算符“&”和“ *”等。因为此代码暂时无法正常工作...
有什么帮助吗? 非常感谢。
编辑:
好的,所以这段代码的目的是在过程结束时获取TextureInfos
对象。 为此,我需要从TextureManager调用getTextureInfos
方法,同时getTextureInfos
从TextureSet
调用getTextureInfos
。
这是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;
};
不,它不起作用,因为它甚至无法编译。 它不编译的原因是因为您尝试返回一个指针作为引用。 指针和引用是两件事。
为了快速,简单且肮脏的修复,请将返回类型从TextureInfos&
更改为TextureInfos*
。
上面概述的快速解决方案是“肮脏的”,因为在使用代码时,会发生内存泄漏(使用new
内存分配内存,但不释放内存)。
这可以通过两种方法解决:要么按值返回,要么不使用指针/引用。 或使用诸如std::unique_ptr
类的智能指针。
如果您可以避免使用动态内存分配,则只需编辑TextureSet::getTextureInfos
以按值返回新的堆栈对象(请注意,如果您担心效率问题,将有一个Return Value Optimization):
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);
}
根据您的对象命名,我假设您要在TextureSet中拥有一组对象。 因此,我建议向您的对象添加一个私有变量,并针对该对象测试新的get请求。 然后,您可以安全地将引用返回给成员。
有人认为,令人非常担忧的是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
已超出范围,因此不再有效!
我无法提出一个简单的解决方案-但您需要确保您了解所创建对象的生命周期管理和所有权问题。 智能指针(返回整个对象而不是引用)通常是其中的关键部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.