Search code examples
c++sfml

Not declared in the scope error, C++ sfml


The compiler error says that "mango" was not declared in the scope. I don't understand why. Mango is a sprite defined in another function in another cpp file. all im trying to do is load a sprite on the screen. I'm sure it's a silly error, I apologize in advance. I'm new to C++.

main.cpp:

#include "test.h"

#include <SFML/Graphics.hpp>

#include <iostream>

/////////////////////////
constexpr int32_t winWidth = 1080;
constexpr int32_t winHeight = 600;



int main()
{


// Rendering SFML window
sf::RenderWindow window(sf::VideoMode({winWidth, winHeight}), "CLICKER GAME");


// Game Loop, Call all functions in here
while (window.isOpen())
{
    sf::Event event;
    while (window.pollEvent(event))
    {
        if (event.type == sf::Event::Closed)
            window.close();
    }

    window.clear(sf::Color(255, 84, 167)); // Magenta

    window.draw(mango);


    window.display();

}

return 0;
}

test.h:

#pragma once

#include <iostream>
#include <string>
class Game
{
public:
    void test();
};

test.cpp:

#include "test.h"

#include <SFML/Graphics.hpp>

#include <iostream>
#include <string>

// Function Defs

void Game::test()
{
    sf::Texture mangoTexture;
    if (!mangoTexture.loadFromFile("Data/mango.png"))
    {
        std::cout << "Load Error";
    }

    sf::Sprite mango;
    mango.setTexture(mangoTexture);



}

Solution

  • Just a quick introduction to scopes in c++. There are a few different ways scoping can work, depending on the type of variable you're using but in general most variables have an automatic scope which means they are created and destroyed automatically. The rules of thumb are:

    1. Any two functions are not correlated with each other in any way. Neither can see what's inside the other.
    2. Any variable with an automatic scope is created where you created, and is deleted at the end of the body you created it in.

    examples:

    void someFunc()
    {//body start of someFunc
    
        if ()
        { //body start of if
    
            while()
            {
            //body of while
            }
    
        } //body end of if
    
    }// body end of someFunc
    
    
    int main() //head of main. main cant see inside body of someFunc. vice versa
    { //body start of function main
    
    } // body end of function main
    
    int main()
    {
        int abc = 4; //abc was created in main body thus exists until main body's end
        if ()
        {
            float bcd; //bcd was created in if body thus...
        }//float exists until this point etc.
    
    
    }//abc exists until this point
    
    //Pretty much the only exception are dynamic variables in basic C++:
    int main()
    {
        int *dyn = new int;
        //important!! the dynamic part here is the 'new int' thats the non-automatic scoped variable. 
    //The int *dyn is an automatic pointer to that scope. after main function ends the pointer is
    //automatically deleted yet the value of the variable still exists in that place in
    //memory until you delete it manually or the program ends completely. not deleting a non-automatic
    //scoped variable ends in memory leaks which lead to unnecessary higher resource usage and
    //slowness of the systme running the program.
    }
    
    //So finally lets say you create a class with some values or something. Lets say they're all automatically scoped.
    1. you can access variables in the class itself.
    2. you can't access variables inside functions.
    
    //Lets use your example:
    //to make it easier to understand lets just make it a simple function instead of a class method(same thing but still)
    void test()
    {
        sf::Texture mangoTexture;
        if (!mangoTexture.loadFromFile("Data/mango.png"))
        {
            std::cout << "Load Error";
        }
    
        sf::Sprite mango;
        mango.setTexture(mangoTexture);
    
    
    
    }
    
    int main()
    {
    //lets say you want to use mango in main. This breaks rule 1 of the aformenthioned 2 rules i wrote at the start:
    main function cannot see whats inside test function. And even if it somehow could, it couldnt use that variable mango because it was destroyed at the end of the function:
    
    //mango doesnt exist hasnt been made yet
    test();
    //mango doesnt exist. has been made and deleted in prev line.
    
    //In the end functions are just packed up code in neat blocks you can recycle and use many times
    return 0;
    }
    
    //If you want to actually use mango in eg main, youd have to either have it as a class variable or have the function return mango
    
    //OPTION 1
    class Game
    {
    public:
        sf::Sprite mango;
        void test()
        {
                sf::Texture mangoTexture;
        if (!mangoTexture.loadFromFile("Data/mango.png"))
        {
            std::cout << "Load Error";
        }
    
        
        mango.setTexture(mangoTexture);
        }
    };
    
    
    //OPTION 2
    class Game
    {
    public:
        sf::Sprite test()
        {
                sf::Texture mangoTexture;
        if (!mangoTexture.loadFromFile("Data/mango.png"))
        {
            std::cout << "Load Error";
        }
    
        sf::Sprite mango;
        mango.setTexture(mangoTexture);
        return mango;
        }
    };
    
    
    //For your case i highly recommend option 1. I wrote both options just as an example as there can be many difficult situations in which you might be forced to only use one or the other.