Thread: Structure requires Constructor

  1. #1
    C++ Enthusiast M.Richard Tober's Avatar
    Join Date
    May 2011
    Location
    Georgia
    Posts
    56

    Question Structure requires Constructor

    I get a warning about initializing the Zone structure's two components (Zone::ZoneCoords & Zone::ZoneMap), then an error stating "synthesized method 'Zone::Zone()' first required in World's initializer list.

    Code:
    #ifndef WORLD_H
    #define WORLD_H
    
    #include <vector>
    #include "constants.h"
    
    struct Coords
    {
        int x;
        int y;
    };
    typedef std::vector<Coords> ZoneLookupTable;
    
    struct Tile
    {
        int ID;
        int Type;
    };
    typedef std::vector<Tile> RowVec;
    typedef std::vector<RowVec> ZoneVec;
    
    struct Zone
    {
        // Why does the compile require this constructor?
        //Zone() : ZoneCoords(), ZoneMap() {}
        Coords ZoneCoords;
        ZoneVec ZoneMap;
    };
    typedef std::vector<Zone> Area;
    
    class World
    {
        public:
            World() : AreaID(1), CurrentZone(), CurrentArea(), ZoneTable(), VecZoneFileNames() {};
            void Load(int ID = 1);
            void Update(float x, float y);
            void Save();
    
            // Helpers
            void CreateZone(float x, float y);
            std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems);
            std::string GenerateZoneFilePath(float x, float y);
            void LoadZones();
    
            // Accessors
            int GetID() { return AreaID; }
            Zone &GetZone() { return CurrentZone; }
            Area &GetArea() { return CurrentArea; }
            ZoneLookupTable &GetZLT() { return ZoneTable; }
    
        private:
            int AreaID;
            Zone CurrentZone;
            Area CurrentArea;
            ZoneLookupTable ZoneTable;
            std::vector<std::string> VecZoneFileNames;
    };
    
    #endif // WORLD_H
    Why does the Zone struct seem to require a constructor be defined?
    I know it's because it contains other structures, but I don't know why. Wouldn't an implicity created default constructor work when I leave out my manually constructed one? I searched for answers with keywords structure and constructor, then relized I wouldn't know the answer if I saw it. Thank you for any time gurus, you make my day.

    As always, go easy on me, and thanks in advance!
    Eventually, I decided that thinking was not getting me very far and it was time to try building.
    — Rob Pike, "The Text Editor sam"

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    From what you have shown it is not possible to tell.

    Your code is #include'ing constants.h (which we can't see) and needs to #include <string> in order to compile.

    The elements of vectors need to have a constructor that accepts no arguments and, in some circumstances, the compiler is prevented from generating them. Such a thing would explain your problem .... except that your code, as shown, does not exhibit such concerns.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    C++ Enthusiast M.Richard Tober's Avatar
    Join Date
    May 2011
    Location
    Georgia
    Posts
    56
    Wow... It should need <string>, but was compiling without it... well - here is the constants.h for acedemic practices.
    Note: Code::Blocks has been flaking out on me a lot lately. Not usually things like this though... how the heck was it compiling. I'm always split between the nitty-gritty world of vim and hand-made makefiles, and the conversely shiny allure of neat IDE's Additional notes: The World class was pulled out of another project to work on independently. The implementation file includes <string>. I'll include the implementation file also for academic potential. Don't laugh.

    constants.h
    Code:
    #ifndef CONSTANTS_H_INCLUDED
    #define CONSTANTS_H_INCLUDED
    
    const bool MUSIC = false;
    const bool DEBUG = false;
    const bool SHOWFPS = true;
    
    // Global System Constants
    const int SCREEN_WIDTH  = 1024;
    const int SCREEN_HEIGHT = 768;
    const int SCREEN_BPP    = 32;
    const char GAME_TITLE[] = "Sellsword";
    
    // Global Game Constants
    const int TILE_WIDTH = 32;
    const int TILE_HEIGHT = 32;
    const int TILE_COLS_X_W = SCREEN_WIDTH / TILE_WIDTH;
    const int TILE_ROWS_Y_H = SCREEN_HEIGHT / TILE_HEIGHT;
    const int TILE_SHEET_COLS = 16;
    const int TILE_SHEET_ROWS = 12;
    const double CHARACTER_SPEED = 200.0;
    
    // Enumerations
    enum {SOUTH, WEST, EAST, NORTH};
    enum {RIGHT_FOOT, MIDDLE_FOOT, LEFT_FOOT};
    enum {MENU_CHOICE_NEW, MENU_CHOICE_LOAD, MENU_CHOICE_QUIT};
    
    // GameState
    enum {INITIALIZING, OPENING, MENU, PLAYING, LOADING, QUITTING, OPTIONS};
    
    // GameStatePlay
    enum {WALKING, SAILING, FLYING, PAUSE, RESTING, COMBAT, TALKING, QSAVE,  QLOAD, OPTS, CUTSCENE, QUIT, EDITMODE, HELPMODE, SCRNSHOT};
    
    #endif // CONSTANTS_H_INCLUDED
    world.cpp
    Code:
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <fstream>
    #include <dirent.h>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include "world.h"
    
    using namespace std;
    
    void World::Load(int ID)
    {
        // Read all valid zone (*.zon) files in the maps directory.
        // Load the zones ending in the AreaID we want.
        // This function uses a logic waterfall to sanity check
        // the file names against a number of criteria.
        AreaID = ID;
    
        // Read the Zones from disk.
        LoadZones();
    
        // Check that 9 usable zones were loaded, lest we create them.
        if (VecZoneFileNames.size() < 9)
        {
            VecZoneFileNames.clear(); // Clear potential damaged or partial zones.
            int w = SCREEN_WIDTH;
            int h = SCREEN_HEIGHT;
            int cx = w/2;
            int cy = h/2;
            CreateZone(cx, cy);     // Center
            CreateZone(cx,   cy-h); // North
            CreateZone(cx+w, cy-h); // Northeast
            CreateZone(cx+w,   cy); // East
            CreateZone(cx+w, cy+h); // Southeast
            CreateZone(cx,   cy+h); // South
            CreateZone(cx-w, cy+h); // Southwest
            CreateZone(cx-w,   cy); // West
            CreateZone(cx-w, cy-h); // Northwest
    
            // Read the Zones from disk.
            LoadZones();
            if (VecZoneFileNames.size() < 9) throw("World::Load: Zone Read error.");
    
        }
    }
    
    void Update(float x, float y)
    //void World::Update(const std::string &ZFP, std::vector<sf::Sprite> &vTS)
    {
    //    ifstream ZoneFile(ZFP.c_str());
    //    string input;
    //    stringstream ss;
    //    vector<string> vInput;
    //    ZoneMap.clear();
    //    while(getline(ZoneFile, input))
    //    {
    //        // Skip comments
    //        if (input[0] != '#')
    //        {
    //            vInput.clear();
    //            // Read in and tokenize line
    //            split(input, ':', vInput);
    //            // convert to ints
    //            //cout << "Debug: vInput size: " << vInput.size() << endl;
    //            unsigned int i = 0;
    //            while (i < vInput.size())
    //            {
    //                int x = atoi(vInput[i].c_str());
    //                int y = atoi(vInput[i+1].c_str());
    //                int tileID = atoi(vInput[i+2].c_str());
    //                i += 3;
    //
    //                Tile NewTile(vTS[tileID], x, y);
    //                //if (DEBUG) cout << "World Loader Data Sample: NewTile.GetPos().y: " << NewTile.GetPos().y << endl;
    //                // push Tiles into [RowMap]
    //                RowMap.push_back(NewTile);
    //            }
    //            ZoneMap.push_back(RowMap);
    //        }
    //    }
    //    ZoneFile.close();
    }
    
    void World::Save()
    {
    //    //Check the ZoneLookUp table
    //    // Save the 8 areas there
    //
    //    CurrentArea
    //    string ZFP = GenerateZonePath(InteriorPoint);
    //
    //    MapVectorZone TZM;
    //    //TZM = LocateZoneMap(TargetZonePath);
    //    TZM = GetZone();  // Place holder
    //
    //    float Time = WorldClock.GetElapsedTime();
    //    cout << "Saving: " << ZFP << endl;
    //    ofstream outfile(ZFP.c_str());
    //
    //    if (!outfile) throw("World::SaveZone: Couldn't open zone file for saving!");
    //    outfile << "# Area Label \"" << string(ZFP).substr(5, 11) << "\"." << endl;
    //    outfile << "# System generated zone file: " << ZFP << endl;
    //    outfile << "# Version 1.2" << endl;
    //
    //    for (int y = 0; y < TILE_ROWS_Y_H; ++y)
    //    {
    //        for(int x = 0; x < TILE_COLS_X_W; ++x)
    //        {
    //            int t = TZM.at(y).at(x).GetID();
    //            outfile << (y < 100 ? "0" : "") << (y < 10 ? "0" : "") << y << ":"
    //                    << (x < 100 ? "0" : "") << (x < 10 ? "0" : "") << x << ":"
    //                    << (t < 100 ? "0" : "") << (t < 10 ? "0" : "") << t;
    //            if (x < TILE_COLS_X_W - 1) outfile << ": ";
    //        }
    //        outfile << endl;
    //        cout << "[]"; // Update status indicator
    //    }
    //
    //    outfile.close();
    //    cout << " Complete!" << endl;
    //    cout << ZFP << " saved in " << (WorldClock.GetElapsedTime() - Time) << " secs."<< endl;
    //
    }
    
    void World::CreateZone(float x, float y)
    {
        string ZoneFileName = GenerateZoneFilePath(x, y);
        /*DEBUG*/cout << "Creating: " << ZoneFileName;
    
        ofstream outfile;
        outfile.open(ZoneFileName.c_str());
        if (!outfile) throw("World::CreatZone: Couldn't open zone file for creation!");
    
        outfile << "# Area Label \"" << string(ZoneFileName).substr(5, 11) << "\"." << endl;
        outfile << "# System generated zone file: " << ZoneFileName << endl;
        outfile << "# Version 1.4" << endl;
    
        // Text Files must be written left to right
        for (int y = 0; y < TILE_ROWS_Y_H; ++y)
        {
            for(int x = 0; x < TILE_COLS_X_W; ++x)
            {
                // Write the ID for tile (1,0) and Walkable Type (000)
                outfile << "001" << ":" << "000";
                if (x < TILE_COLS_X_W - 1) outfile << ": ";
            }
            outfile << endl;
        }
        outfile.close();
        cout << " Complete!" << endl;
    }
    
    // Helper for Loader
    std::string World::GenerateZoneFilePath(float x, float y)
    {
        char  SignX = x > -1 ? 'P' : 'N';
        char  SignY = y > -1 ? 'P' : 'N';
        int coord_x = abs(static_cast<int>(x) / SCREEN_WIDTH);
        int coord_y = abs(static_cast<int>(y) / SCREEN_HEIGHT);
    
        stringstream ZoneName;
    
        ZoneName << "maps/";
        ZoneName << SignX << (coord_x < 100 ? "0" : "") << (coord_x < 10 ? "0" : "") << coord_x;
        ZoneName << SignY << (coord_y < 100 ? "0" : "") << (coord_y < 10 ? "0" : "") << coord_y;
        ZoneName << "A"   << (AreaID  < 100 ? "0" : "") << (AreaID < 10 ? "0" : "") << AreaID << ".zon";
    
        /*DEBUG*/ cout << "World::GenerateZoneFilePath(" << x << "," << y << "):" << endl;
        cout << "\"" << ZoneName.str() << "\"" << endl;
        return ZoneName.str();
    }
    
    std::vector<std::string> &World::split(const std::string &s, char delim, std::vector<std::string> &elems)
    {
        std::stringstream ss(s);
        std::string item;
        while(std::getline(ss, item, delim)) {
            elems.push_back(item);
        }
        return elems;
    }
    
    void World::LoadZones()
    {
        DIR *DirPtr;
        struct dirent *DirEntry;
    
        if((DirPtr = opendir("maps")))
        {
            while ((DirEntry = readdir(DirPtr)))
            {
                string CurrFile(DirEntry->d_name);
                if(CurrFile.length() == 16)
                    if(CurrFile[8] == 'A')
                        if(atoi(string(CurrFile.substr(9, 3)).c_str()) == AreaID)
                            if(CurrFile[0] == 'P' || CurrFile[0] == 'N')
                                if(CurrFile[4] == 'P' || CurrFile[4] == 'N')
                                    if(CurrFile.compare(12, 4, ".zon") == 0)
                                        VecZoneFileNames.push_back(CurrFile.substr(0, 12));
            }
            closedir(DirPtr);
        }
        else throw("[World::Load]: No maps directory found. (ex: ./maps/N000P000A001.zon)");
    }
    Eventually, I decided that thinking was not getting me very far and it was time to try building.
    — Rob Pike, "The Text Editor sam"

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Is it a warning or an error? What is the compiler (Code::Blocks is not a compiler) and the flags?
    Your code should not produce an error and I don't see any reason to warn about synthesized default constructor either.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    C++ Enthusiast M.Richard Tober's Avatar
    Join Date
    May 2011
    Location
    Georgia
    Posts
    56
    Quote Originally Posted by anon View Post
    Is it a warning or an error? What is the compiler (Code::Blocks is not a compiler) and the flags?
    Your code should not produce an error and I don't see any reason to warn about synthesized default constructor either.
    My Errors without the constructor:
    Code:
    ||=== Test, Debug ===|
    include/world.h||In constructor ‘Zone::Zone()’:|
    include/world.h|24|warning: ‘Zone::ZoneCoords’ should be initialized in the member initialization list|
    include/world.h|24|warning: ‘Zone::ZoneMap’ should be initialized in the member initialization list|
    include/world.h||In constructor ‘World::World()’:|
    include/world.h|34|note: synthesized method ‘Zone::Zone()’ first required here |
    include/world.h||In constructor ‘Zone::Zone()’:|
    include/world.h|24|warning: ‘Zone::ZoneCoords’ should be initialized in the member initialization list|
    include/world.h|24|warning: ‘Zone::ZoneMap’ should be initialized in the member initialization list|
    include/world.h||In constructor ‘World::World()’:|
    include/world.h|34|note: synthesized method ‘Zone::Zone()’ first required here |
    ||=== Build finished: 2 errors, 4 warnings ===|
    gcc 4.5.2!
    I know, I know. That's why I was like, "huh?"

    Code:
    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.5.2/lto-wrapper
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.5.2-8ubuntu4' --with-bugurl=file:///usr/share/doc/gcc-4.5/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.5 --enable-shared --enable-multiarch --with-multiarch-defaults=x86_64-linux-gnu --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib/x86_64-linux-gnu --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.5 --libdir=/usr/lib/x86_64-linux-gnu --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-gold --enable-ld=default --with-plugin-ld=ld.gold --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
    Thread model: posix
    gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)
    Last edited by M.Richard Tober; 01-24-2012 at 06:15 AM.
    Eventually, I decided that thinking was not getting me very far and it was time to try building.
    — Rob Pike, "The Text Editor sam"

  6. #6
    C++ Enthusiast M.Richard Tober's Avatar
    Join Date
    May 2011
    Location
    Georgia
    Posts
    56
    I solved it more or less. I restructured and rethought the taxonomy for my classes. This in turn seemed to alleviate some sort of circular name clash. Wish I knew more, but at least it's cleaned up.

    world.h
    Code:
    #ifndef WORLD_H
    #define WORLD_H
    
    #include <vector>
    #include <string>
    #include "constants.h"
    
    struct Coords
    {
        int x;
        int y;
    };
    
    struct Tile
    {
        int ID;
        int Type;
    };
    
    typedef std::vector<std::string> VecString;
    typedef std::vector<Tile> Row;
    typedef std::vector<Row> Zone;
    typedef std::vector<Zone> Area;
    
    struct ZoneHeader
    {
        Coords ZoneCoords;
        Zone ZoneMap;
    };
    
    class World
    {
        public:
            World() : AreaID(1), LocalArea(9), TotalArea(100), VecZoneFileNames(9) {};
    
            void Load(int ID = 1);
            void Update(float x, float y);
            void Save();
    
            // Helpers
            void LoadZones();
            void CreateZone(float x, float y);
            std::string GenerateZoneFilePath(float x, float y);
            std::vector<std::string> &split(const std::string &s,
                std::vector<std::string> &elems, char delim = ' ');
    
            // Accessors
            ///int GetID() { return AreaID; }
            Area &GetArea() { return TotalArea; }
            Area &GetLocalArea() { return LocalArea; }
    
        private:
            int AreaID;
            Area LocalArea;
            Area TotalArea;
            VecString VecZoneFileNames;
    };
    
    #endif // WORLD_H
    Eventually, I decided that thinking was not getting me very far and it was time to try building.
    — Rob Pike, "The Text Editor sam"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How do I know which function requires a '-lsomething'?
    By hkuser2001 in forum C Programming
    Replies: 1
    Last Post: 05-09-2006, 05:39 AM
  2. PC Game project requires c++ programmers
    By drallstars in forum Projects and Job Recruitment
    Replies: 2
    Last Post: 02-22-2006, 12:23 AM
  3. Replies: 9
    Last Post: 10-26-2005, 07:29 AM
  4. Programs requires portforwarding
    By Da-Nuka in forum Networking/Device Communication
    Replies: 6
    Last Post: 08-28-2005, 12:45 PM
  5. C Moron requires Mucho helpo!
    By tom0987654321 in forum C Programming
    Replies: 5
    Last Post: 04-30-2002, 01:41 PM

Tags for this Thread