Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Pls take look at one class I created, exam if reference/pointer logic correct  (Read 1410 times)

0 Members and 1 Guest are viewing this topic.

S_BISHOP

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Hello I have spent the past month ready C++ Book Jumping Into C++, great book and great author.
This was after I had been pointed out on this forum that I have not learnt C++, and needed to.
Now I have, to I think an intermediate grasp of understanding,  I may read the whole thing from start to finish a second time, to concrete my understanding.

I would like to know If there is any incorrect Reference/Pointer logic in my class LevelManager.

By viewing this class, this is asuming the rest of my classes behave and are structured as how you would expect them to be in a somewhat generic game engine like structure.

I think I have done somethings in correct with datatypes and vectors, but not likley program flor structure, this is the way I intended it to run.

Problem:

Vector container  activeLevelPlatformables, will not store the Platformable objects, I,m not sure why ?
the vector prints out with a size of 0.


The good new is you don,t have to read most of it, up until you get to the doted line of the .cpp file , because its works as expected up until this point.

take not of this comment:
// Bug: Platformable memory addresses do not store in pointer vector



Please take a look thanks.




This is the structure:

                 Spritable
       _________|       |_________
       |                              |
      PlayableAIable            LevelStructurable
      |      |                    |                         |      
   Playable   AIable          Platformable     NonPlatformable


note: This class LevelManager is not part of this inheritance heir achy.


note: the comments need to be updated since I last typed them




/*
*/



#ifndef LEVELMANAGER_H
#define LEVELMANAGER_H

#include <Platformable.h>

#include <Vector>
#include <string>

class LevelManager
{
    public:

        LevelManager();
        ~LevelManager();

        void loadActiveLevel();
        std::vector<Platformable*> getActiveLevelPlatformables();

    private:

        const int LEVEL_NUM_TOTAL;

        const std::string FILE_PATH_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT, FILE_PATH_ALL_LEVEL_STRUCTURES_IMAGES;

        // A marker point storing the last value read offset
        // to begin loading vector currentLevelStructuresXYPos, with each call of function loadAcativeLevel();
        int lastReadTokenCounterAllLevelStructuresXYPos, lastReadTokenCounterAllLevelStructuresWidthHeight, lastReadTokenCounterAllLevelStructuresImages;

        // This vector is reset and loaded with a new set of values, each time the function loadActiveLevels() is called
        // The values loaded in the vector are dependent on the value of the lastReadTokenCounter
        std::vector<int> activeLevelStructuresXYPos, activeLevelStructuresWidthHeight;
        std::vector<std::string> activeLevelStructuresImages;

        // A pointer is required to store enough memory bytes to allocate variable size objects and its member variables of this type
        std::vector<Platformable*> activeLevelPlatformables;
};

#endif // LEVELMANAGER_H


 




#include "LevelManager.h"
#include <Platformable.h>

#include <Vector>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <iterator>


LevelManager::LevelManager()
: LEVEL_NUM_TOTAL(100), FILE_PATH_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT("res/allLevelsStructuresXYWidthHeight.txt"), FILE_PATH_ALL_LEVEL_STRUCTURES_IMAGES("res/allLevelsStructuresImages.txt")
{
    int proportionalInitVal = 0;
    lastReadTokenCounterAllLevelStructuresXYPos = proportionalInitVal;
    lastReadTokenCounterAllLevelStructuresWidthHeight = proportionalInitVal;
    lastReadTokenCounterAllLevelStructuresImages = proportionalInitVal;
}

LevelManager::~LevelManager()
{
}

std::vector<Platformable*> LevelManager::getActiveLevelPlatformables(){return activeLevelPlatformables;}

void LevelManager::loadActiveLevel(){

    // notes about this function
    // >=   =  (equal to) operator, of the conditions is only applicable to the intital run of this function
    // >=   >  (greater than sign), of the conditions is applicable after the intial function run


    // Clears all active level temperary resource vector collections
    activeLevelStructuresXYPos.clear();
    activeLevelStructuresImages.clear();



    int findLastTokenReadCounter = 0;
    std::string readLine;



    // Reads and stores the x y positions of the required structures of the active level

    std::ifstream FILE_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT;
    std::string readValueX, readValueY, readValueWidth, readValueHeight;

    FILE_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT.open(FILE_PATH_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT);

    if (FILE_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT.is_open()) {
        std::cout << "File " << FILE_PATH_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT << " was opened Successfully" << std::endl << std::endl;
        std::cout << "platformableStructuresXYAllLevels.txt : Active level Structures x y values" << std::endl;

        while(getline(FILE_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT, readLine)){

            findLastTokenReadCounter++;

            if(findLastTokenReadCounter >= lastReadTokenCounterAllLevelStructuresXYPos) {
                if (FILE_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT >> readValueX) {
                    int readValueXToInt;
                    std::stringstream(readValueX) >> readValueXToInt;
                    activeLevelStructuresXYPos.push_back(readValueXToInt);
                    lastReadTokenCounterAllLevelStructuresXYPos++;

                    std::cout << readValueXToInt << " ";
                }

                if (FILE_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT >> readValueY) {
                    int readValueYToInt;
                    std::stringstream(readValueY) >> readValueYToInt;
                    activeLevelStructuresXYPos.push_back(readValueYToInt);
                    lastReadTokenCounterAllLevelStructuresXYPos++;

                    std::cout << readValueYToInt << " ";
                }
            }

            if(findLastTokenReadCounter >= lastReadTokenCounterAllLevelStructuresWidthHeight) {

                findLastTokenReadCounter++;

                if (FILE_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT >> readValueWidth) {
                    int readValueWidthToInt;
                    std::stringstream(readValueWidth) >> readValueWidthToInt;
                    activeLevelStructuresWidthHeight.push_back(readValueWidthToInt);
                    lastReadTokenCounterAllLevelStructuresWidthHeight++;

                    std::cout << readValueWidthToInt << " ";
                }

                 if (FILE_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT >> readValueHeight) {
                    int readValueHeightToInt;
                    std::stringstream(readValueHeight) >> readValueHeightToInt;
                    activeLevelStructuresWidthHeight.push_back(readValueHeightToInt);
                    lastReadTokenCounterAllLevelStructuresWidthHeight++;

                    std::cout << readValueHeightToInt << " ";
                }
            }
                std::cout << std::endl;
        }
    }
    else {
        std::cout << " : File " << FILE_PATH_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT << " was not opened Successfully" << std::endl;
    }

    FILE_ALL_LEVEL_STRUCTURES_XY_WIDTH_HEIGHT.close();



    findLastTokenReadCounter = 0;
    readLine = "";


    // Reads and stores the image resources of each structure of the active level

    std::ifstream FILE_ALL_LEVEL_STRUCTURES_IMAGES;
    std::string readValueImage;


    FILE_ALL_LEVEL_STRUCTURES_IMAGES.open(FILE_PATH_ALL_LEVEL_STRUCTURES_IMAGES);

    if (FILE_ALL_LEVEL_STRUCTURES_IMAGES.is_open()) {
        std::cout << std::endl << std::endl << "File " << FILE_PATH_ALL_LEVEL_STRUCTURES_IMAGES << " was opened Successfully" << std::endl << std::endl;
        std::cout << "res/allLevelsStructuresImages.txt : Active level structures image values" << std::endl;

        while(getline(FILE_ALL_LEVEL_STRUCTURES_IMAGES, readLine)){

            findLastTokenReadCounter++;

            if(findLastTokenReadCounter >= lastReadTokenCounterAllLevelStructuresImages){
                if (FILE_ALL_LEVEL_STRUCTURES_IMAGES >> readValueImage) {
                    activeLevelStructuresImages.push_back(readValueImage);
                    lastReadTokenCounterAllLevelStructuresImages++;

                    std::cout << readValueImage << " ";
                }

                std::cout << std::endl;
            }
        }
    }
    else {
        std::cout << " : File " << FILE_PATH_ALL_LEVEL_STRUCTURES_IMAGES << " was not opened Successfully" << std::endl;
    }

    FILE_ALL_LEVEL_STRUCTURES_IMAGES.close();




// ----------------------------------------start looking here-------------------------------------------------------------------------

  // Bug: Platformable memory addresses do not store in Platformable pointer vector:   activeLevelPlatformables





    // Reads and loads visible resources and draws the structures of the active level

    int sortCounter = 0;
    for (std::vector<Platformable*>::size_type i = 0 ; i != activeLevelStructuresXYPos.size(); i++) {
        Platformable p;

        if (sortCounter == 0) {
                double tempValX = activeLevelStructuresXYPos[i];
                p.setX(tempValX);
                sortCounter++;
                break;
        } else if (sortCounter == 1) {
                double tempValY = activeLevelStructuresXYPos[i];
                p.setY(tempValY);
                sortCounter++;
                break;
        }  else if (sortCounter == 2) {
                double tempValWidth = activeLevelStructuresWidthHeight[i];
                p.setWidth(tempValWidth);
                sortCounter++;
                break;
        }  else if (sortCounter == 3) {
                double tempValHeight = activeLevelStructuresWidthHeight[i];
                p.setHeight(tempValHeight);
                sortCounter++;
                break;
        } else if (sortCounter > 3) {
            sortCounter = 0;
        }

        p.getTexture().loadFromFile(activeLevelStructuresImages[i], sf::IntRect(p.getX(), p.getY(), p.getWidth(), p.getHeight()));
        activeLevelPlatformables.push_back(&p);
    }



    // testing

    std::cout << std::endl << std::endl;

    std::cout << "The vector activeLevelStructuresXYPos size = " << activeLevelStructuresXYPos.size() << std::endl;;
    for(int value : activeLevelStructuresXYPos) {
        std::cout << value << " ";
    }

    std::cout << std::endl << std::endl;

    std::cout << "The vector activeLevelStructuresWidthHeight size = " << activeLevelStructuresWidthHeight.size() << std::endl;
    for(int value : activeLevelStructuresWidthHeight) {
        std::cout << value << " ";
    }

    std::cout << std::endl << std::endl;

    std::cout << "The vector activeLevelStructuresImages size = " << activeLevelStructuresImages.size() << std::endl;
    for(std::string value : activeLevelStructuresImages) {
        std::cout << value << " ";
    }

    std::cout << std::endl << std::endl;

 

    std::cout << "The vector activeLevelPlatformables size = " << activeLevelPlatformables.size() << std::endl;

    std::cout << std::endl << std::endl;

    for (std::vector<Platformable*>::size_type i = 0; i != activeLevelPlatformables.size(); i++) {
        std::cout << activeLevelPlatformables[i]->getX() << activeLevelPlatformables[i]->getY() << " " << activeLevelPlatformables[i]->getWidth() << " " << activeLevelPlatformables[i]->getHeight();
    }

}


 

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Generally don't post such big examples, but keep your code minimal and complete.

    for(...) {
        Platformable p;
        // ...
        activeLevelPlatformables.push_back(&p);
    }

When you push back a pointer of the local p object, what do you think will happen?

You create a local instance, push a pointer of that instance onto the vector, then the loop body ends and the local instance will be deleted and the saved pointer will turn into a wild pointer, meaning it points to a destroyed object. And that will repeat in a loop for all objects.

You should read up again on how pointers and std::vectors work.

Save the actual object in the vector and not a pointer to the object.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

S_BISHOP

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Thanks mate, will not post big examples next time, I thought the error lied in everything you have explained, but yes wild pointers.
I appreciate your post , constructive and fair from programmer to programmer.
Have a good day :)

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Hello I have spent the past month ready C++ Book Jumping Into C++, great book and great author.
This was after I had been pointed out on this forum that I have not learnt C++, and needed to.
Great. Good for you - if there's any way I can help you out in the future, I'll be happy to.
If only more people had this attitude...

 

anything