2014-12-02 54 views
0

使用SFML 2.1無法在類sf :: NonCopyable中訪問私有成員。該副本在哪裏? C++

我決定做一個包含我的音頻文件的對象。然而,當我跑我的測試,我得到以下錯誤:

錯誤C2248:「SF ::不可複製::不可複製」:不能訪問類中聲明私有成員「SF ::不可複製」

我看着在SFML網站上提供了關於這個錯誤的一些信息,並且聲明我無法複製繼承sf :: NonCopyable(我認爲)的對象。這些對象可能是sf :: Sound和sf :: Music,因爲我即將展示。真正的問題是:這份複印件在哪裏,我該如何解決?

音頻類

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]; 
    } 
}; 

負載聽起來方法

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; 
} 
+4

'的std :: pair'做到這一點總體上使副本,然後將其插入到地圖中創建另一個。也許你想使用'std :: unique_ptr'或'std :: shared_ptr'來代替? – Cameron 2014-12-02 19:49:49

+0

你使用C++ 11嗎?你可能能夠使用新的移動語法 - 基本上改變你的addSound,addMusic等功能來取得聲音&&等。 – ventsyv 2014-12-02 20:00:13

+0

@Bash音樂似乎是唯一不可複製的對象在這裏涉及(因爲它包含一個'sf :: Thread' )。你可能不得不使用指向'sf :: Music'的指針。由於SFML傢伙沒有實現移動構造器,它幾乎是你唯一的選擇。噢,複製是在這行'musics.insert(std :: pair (key,m));' – PeterT 2014-12-02 22:06:14

回答

1

第一樣已經提到的意見,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); 
} 
相關問題