C++ 无法访问类sf::NonCopyable中的私有成员。副本在哪里?C++;
使用SFML 2.1 我决定制作一个包含我的音频文件的对象。但是,当我运行测试时,会出现以下错误: 错误C2248:“sf::NonCopyable::NonCopyable”:无法访问在类“sf::NonCopyable”中声明的私有成员 我在SFML网站上查找了一些有关此错误的信息,它指出我无法复制继承sf::NonCopyable(我想)的对象。正如我将要展示的,这些对象可能是sf::Sound和sf::Music。真正的问题是:这个拷贝是在哪里制作的,我如何修复它 音频类C++ 无法访问类sf::NonCopyable中的私有成员。副本在哪里?C++;,c++,sfml,C++,Sfml,使用SFML 2.1 我决定制作一个包含我的音频文件的对象。但是,当我运行测试时,会出现以下错误: 错误C2248:“sf::NonCopyable::NonCopyable”:无法访问在类“sf::NonCopyable”中声明的私有成员 我在SFML网站上查找了一些有关此错误的信息,它指出我无法复制继承sf::NonCopyable(我想)的对象。正如我将要展示的,这些对象可能是sf::Sound和sf::Music。真正的问题是:这个拷贝是在哪里制作的,我如何修复它 音频类 struct
struct Audio {
std::map<std::string, sf::Sound> sounds;
std::map<std::string, sf::Music> musics;
Audio() : sounds(),
musics(){}
void addSound(sf::Sound& s, sf::SoundBuffer& sb, std::string key){
s.setBuffer(sb);
sounds.insert(std::pair<std::string, sf::Sound>(key, s));
}
void addSound(sf::Sound& s, std::string key){
sounds.insert(std::pair<std::string, sf::Sound>(key, s));
}
void addMusic(sf::Music& m, std::string key){
musics.insert(std::pair<std::string, sf::Music>(key, m));
}
sf::Sound& getSound(std::string key){
return sounds[key];
}
sf::Music& getMusic(std::string key){
return musics[key];
}
};
struct音频{
地图声音;
地图音乐;
音频():声音(),
音乐(){}
void addSound(sf::Sound&s、sf::SoundBuffer&sb、std::string键){
s、 塞布弗(sb);
插入(std::pair(key,s));
}
void addSound(sf::Sound&s,std::string键){
插入(std::pair(key,s));
}
void addMusic(sf::Music&m,std::string键){
音乐。插入(标准::对(键,m));
}
sf::Sound和getSound(标准::字符串键){
返回声音[键];
}
sf::Music和getMusic(std::string键){
返回音乐[键];
}
};
加载声音方法
void loadSounds(Audio& audio){
sf::Music backgroundMusic;
sf::Sound eating;
sf::SoundBuffer sb_eating;
sf::Sound moving;
sf::SoundBuffer sb_moving;
sf::Sound losing;
sf::SoundBuffer sb_losing;
sf::Sound begin;
sf::SoundBuffer sb_begin;
if (!backgroundMusic.openFromFile("backgroundmusic.wav"))
std::cerr << "Error opening \"backgroundmusic.wav\"" << std::endl;
if (!sb_eating.loadFromFile("eatingsfx.wav"))
std::cerr << "Error opening \"eatingsfx.wav\"" << std::endl;
if (!sb_moving.loadFromFile("movingsfx.wav"))
std::cerr << "Error opening \"movingsfx.wav\"" << std::endl;
if (!sb_losing.loadFromFile("losingsfx.wav"))
std::cerr << "Error opening \"losingsfx.wav\"" << std::endl;
if (!sb_begin.loadFromFile("beginsfx.wav"))
std::cerr << "Error opening \"beginsfx.wav\"" << std::endl;
eating.setBuffer(sb_eating);
moving.setBuffer(sb_moving);
losing.setBuffer(sb_losing);
begin.setBuffer(sb_begin);
audio.addMusic(backgroundMusic, std::string("backgroundMusic"));
audio.addSound(eating, std::string("eating"));
audio.addSound(moving, std::string("moving"));
audio.addSound(losing, std::string("losing"));
audio.addSound(begin, std::string("begin"));
}
int main(){
/*Initialize the objects*/
Snake snake = Snake();
Audio& audios = Audio();
sf::Text textCount;
Apple apple(0, 0);
apple.locateApple();
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "SFML Application" );
/*Load the audio*/
loadSounds(audios);
audios.getMusic("backgroundMusic").setVolume(10);
audios.getMusic("backgroundMusic").setLoop(true);
audios.getMusic("backgroundMusic").setVolume(25);
/*Load the font*/
sf::Font font;
if (!(font.loadFromFile("arial.ttf")))
std::cout << "Error loading fonts" << std::endl;
/*Create the text*/
textCount.setFont(font);
textCount.setString(std::string("points: ") + std::to_string(points));
textCount.setColor(sf::Color::Red);
textCount.setCharacterSize(20);
textCount.setPosition(windowWidth / 2 - (textCount.getString().getSize()*(textCount.getCharacterSize() / 5)), textCount.getCharacterSize() - 5);
textCount.setStyle(sf::Text::Bold);
window.draw(textCount);
/*Set Framerate fps*/
window.setFramerateLimit(10);
/*MAIN GAME LOOP*/
counterTick = 1;
audios.getSound("begin").play();
audios.getMusic("backgroundMusic").play();
while (inGame)
{
std::string counter = std::to_string(counterTick);
std::cout << "Tick: " + counter << std::endl;
window.clear(sf::Color::Black);
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Escape)) break;
/*Call Updates*/
snake.input();
snake.checkReals();
snake.moveUpdate();
audios.getSound("moving").play();
/*Call Collisions*/
std::cout << " Outside Collision Loop " << std::endl;
checkApple(snake, apple, audios.getSound("eating"));
checkBoundary(snake);
/*Call Draw*/
std::vector<sf::RectangleShape> shapearray = snake.draw();
for (int i = shapearray.size() - 1; i >= 0; i--){
window.draw(shapearray[i]);
}
window.draw(textCount);
window.draw(apple.draw());
window.display();
counterTick++;
}
audios.getSound("losing").play();
audios.getMusic("backgroundMusic").stop();
std::system("PAUSE");//bad practice, debuggin purposes
return 0;
}
void loadSounds(音频和音频){
音乐背景音乐;
健康饮食;
sf::声音缓冲;某人吃东西;
sf::声音移动;
sf::声音缓冲器sb_移动;
sf::声音丢失;
sf::声音缓冲器sb_丢失;
sf::声音开始;
sf::声音缓冲区sb_开始;
如果(!backgroundMusic.openFromFile(“backgroundMusic.wav”))
std::cerr就像前面提到的评论一样,sf::Music
无法复制。您最好将其包装在一个std::unique_ptr
中,因为您不需要共享所有权
因为你在前面的问题中说过你是为学校做这件事的,所以我将向你展示如何用C++11来做这件事
#include <string>
#include <map>
#include <memory>
//non copyable and non movable like sf::Music
struct NonCopyable
{
NonCopyable() {};
NonCopyable(const NonCopyable &&other) = delete;
NonCopyable(const NonCopyable &other) = delete;
void randomFunc(){}
};
struct MapHolder
{
std::map<std::string, std::unique_ptr<NonCopyable>> container;
void addElement(const std::string &key, std::unique_ptr<NonCopyable> value)
{
//std::move is necessary here, compiler error without it, since
//unique_ptr<T> is non-copyable but can be moved just fine
container.insert({key , std::move(value)});
}
NonCopyable &get(const std::string &key)
{
//using container[key] will create a new NonCopyable if none is found
//this will however throw an exception if key is not in the map
return *container.at(key);
}
//probably not necessary in this case but this is so that you can get a
//const NonCopyable elements from a "const MapHolder", without this,
//calling ".get" on a "const MapHolder" would be an error
const NonCopyable &get(const std::string &key) const
{
return *container.at(key);
}
};
int main()
{
MapHolder holder;
auto myInstance = std::make_unique<NonCopyable>();
//if make_unique is not supported on your compiler use this:
//auto myInstance = std::unique_ptr<NonCopyable>(new NonCopyable());
//this is how you access members of NonCopyable
myInstance->randomFunc();
//again, the move here is necessary, since std::unique_ptr is non-copyable
//after this line "myInstance" is invalid
holder.addElement("test", std::move(myInstance));
//doing this is illegal now, since myInstance is now moved
//it should be noted that std::move was only a cast, the actual moving
//happened because "addElement" took the unique_ptr by value and
//thereby transferred the ownership during construction of its local parameter
//myInstance->randomFunc();
//this is ok
holder.get("test").randomFunc();
//this is fine too
NonCopyable &local_ref = holder.get("test");
local_ref.randomFunc();
return(0);
}
#包括
#包括
#包括
//不可复制且不可移动,如sf::Music
结构不可复制
{
不可复制(){};
不可复制(const NonCopyable&&other)=删除;
不可复制(const NonCopyable&other)=删除;
void randomFunc(){}
};
结构映射器
{
映射容器;
void addElement(常量std::字符串和键,std::唯一值)
{
//std::move在这里是必需的,没有它的编译器错误,因为
//unique_ptr不可复制,但可以很好地移动
insert({key,std::move(value)});
}
不可复制和获取(const std::string和key)
{
//如果找不到新的不可复制项,则使用容器[key]将创建一个新的不可复制项
//但是,如果键不在映射中,这将引发异常
返回*容器at(键);
}
//在这种情况下可能没有必要,但这是为了让您能够
//来自“常量映射持有者”的常量不可复制元素,
//在“常量映射持有者”上调用“.get”将是一个错误
常量不可复制和获取(常量标准::字符串和键)常量
{
返回*容器at(键);
}
};
int main()
{
地图持有人;
auto myInstance=std::make_unique();
//如果编译器不支持make_unique,请使用以下方法:
//auto myInstance=std::unique_ptr(新的NonCopyable());
//这是访问非复制成员的方式
myInstance->randomFunc();
//同样,这里的移动是必要的,因为std::unique_ptr是不可复制的
//该行后面的“myInstance”无效
holder.addElement(“测试”,标准::移动(myInstance));
//现在这样做是非法的,因为myInstance现在已被移动
//应该注意的是,std::move只是一个cast,即实际的移动
//发生的原因是“addElement”按值和
//从而在其局部参数的构造过程中转让了所有权
//myInstance->randomFunc();
//这没关系
holder.get(“test”).randomFunc();
//这也很好
不可复制和本地_ref=持有者获取(“测试”);
局部_ref.randomFunc();
返回(0);
}
>代码> STD::配对< /代码>创建一个副本,然后将其插入到另一个地图中。也许你想使用<代码> STD::UnQuyGyPTR < /C> >或>代码> STD::SyrdYPPTR < /C> >你使用C++ 11吗?你可以使用新的移动语法——基本上改变你的AddioDead、AddiMoice等功能来获取声音和其他@ BASH音乐SE。ems将是此处涉及的唯一不可复制对象(因为它包含sf::Thread
)。您可能必须使用指向sf::Music
的指针。由于SFML人员没有实现移动构造函数,这几乎是您唯一的选择。哦,复制是在这一行Music.insert(std::pair(key,m));