0

I have very recently began learning C++ and I've been stuck on this error for a while now. Searching for similar questions has not yielded me an answer.

part of main.cpp:

#include <SDL.h>
#include <SDL_image.h>
#include <iostream>
#include <string>
#include "spritesheet.h"
using namespace std;

spriteSheet charimage("../img/char.png");
spriteSheet bgimage("../img/bg.png");

class playerSprite
{
    public:
        playerSprite(int xpos, int ypos, spriteSheet sheet);

        int pos[2]; // player postition
        spriteSheet image;
};

playerSprite::playerSprite(int xpos, int ypos, spriteSheet sheet)
{
    pos[0] = xpos;
    pos[1] = ypos;
    image = sheet;
}

playerSprite player(0, 0, charimage);

spritesheet.h:

#ifndef LTEXTURE_H
#define LTEXTURE_H
using namespace std;

extern SDL_Renderer* screen;

class spriteSheet //Texture wrapper for all game objects
{
    SDL_Texture* sheet;
    SDL_Rect ssize;

    public:
        spriteSheet(string path);
        ~spriteSheet();
        void setClip(int x = 0, int y = 0, int w = 0, int h = 0);
        void render(int x = 0, int y = 0);
        void free();

        SDL_Rect sclip;

};

#endif // LTEXTURE_H

part of spritesheet.cpp:

#include <SDL.h>
#include <SDL_image.h>
#include <iostream>
#include <string>
#include "spritesheet.h"
using namespace std;

spriteSheet::spriteSheet(string path)
{
    SDL_Texture* newTexture = NULL;
    SDL_Surface* loadedSurface = IMG_Load(path.c_str());

    if(loadedSurface == NULL)
    {
        cout << IMG_GetError() << endl;
    }
    else
    {
        newTexture = SDL_CreateTextureFromSurface(screen, loadedSurface);
        if(newTexture == NULL)
        {
            cout << SDL_GetError() << endl;
        }
        else
        {
            ssize.w, sclip.w = loadedSurface->w;
            ssize.h, sclip.h = loadedSurface->h;
        }
        SDL_FreeSurface(loadedSurface);
    }
    sheet = newTexture;
}

When I construct my playerSprite object, I want to pass in a spriteSheet object for it. I have gotten this code to compile by having functions like playerSprite::setSheet() and spriteSheet::setImage() but I cannot get it to work with constructors. Every time I try to compile I get this error:

C:\Users\Platino\Documents\C++\Dragorogue\main.cpp  In constructor 'playerSprite::playerSprite(int, int, spriteSheet)':
20  65  C:\Users\Platino\Documents\C++\Dragorogue\main.cpp  [Error] no matching function for call to 'spriteSheet::spriteSheet()'
20  65  C:\Users\Platino\Documents\C++\Dragorogue\main.cpp  [Note] candidates are:
5   0   C:\Users\Platino\Documents\C++\Dragorogue\main.cpp  In file included from main.cpp
13  3   C:\Users\Platino\Documents\C++\Dragorogue\spritesheet.h [Note] spriteSheet::spriteSheet(std::string)
13  3   C:\Users\Platino\Documents\C++\Dragorogue\spritesheet.h [Note] candidate expects 1 argument, 0 provided
7   7   C:\Users\Platino\Documents\C++\Dragorogue\spritesheet.h [Note] spriteSheet::spriteSheet(const spriteSheet&)
7   7   C:\Users\Platino\Documents\C++\Dragorogue\spritesheet.h [Note] candidate expects 1 argument, 0 provided

EDIT:

The method suggested by LogicStuff would force me to initialize a new SpriteSheet object every time I construct a new playerSprite object. I want to create a single SpriteSheet object and have all playerSprite objects use that.

DragonDePlatino
  • 159
  • 1
  • 10
  • Possible duplicate of [Why should I prefer to use member initialization list?](http://stackoverflow.com/questions/926752/why-should-i-prefer-to-use-member-initialization-list) – LogicStuff Feb 14 '16 at 00:20
  • First, do you know why you get that error? Or you do know why, but asking how to fix it? – PaulMcKenzie Feb 14 '16 at 00:52
  • I do not know why I am getting that error. People with similar issues have messed up their #include declarations or passed the wrong arguments when constructing their object, but I don't think I'm doing either of those. If I remove the playerSprite class and player object I don't get any errors. – DragonDePlatino Feb 14 '16 at 00:56
  • Look at the answer I gave. The error is there because your `playerSprite` object has to construct the `spriteSheet` member, but `spriteSheet` constructor requires one argument. The only way to do this is with the member-init list. – PaulMcKenzie Feb 14 '16 at 01:17

1 Answers1

0

Since your spriteSheet object doesn't have a default constructor, the issue is that you have a spriteSheet member in the playerSprite class that requires construction with one argument. That member is image.

class spriteSheet 
{
        spriteSheet(string path);  // <-- This is your constructor
};

class playerSprite
{
    public:
        playerSprite(int xpos, int ypos, spriteSheet sheet);  
        spriteSheet image;  // <-- This member has to be initialized on construction.
};

On construction of a playerSprite, the spriteSheet member must be initialized. The only way to initialize the image member is to construct it with one argument within the member initialization list:

playerSprite::playerSprite(int xpos, int ypos, spriteSheet sheet) :
                           image("somestring") 
{
  //...
}

Note -- code within the body of the constructor (between the { }) is not initialization. It is assignment -- a big difference. To initialize, you must use the member-initialization list.

Also, you should be passing spriteSheet by const reference, not by value:

playerSprite::playerSprite(int xpos, int ypos, const spriteSheet& sheet) :
                           image("somestring") 
{
   image = sheet;  // now we can assign.
}

Once inside the constructor, then you can do an assignment to the member:

Here is a small sample

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • At your suggestion I tried member initialization lists and changing my function arguments for an hour. Neither worked so I'm reverting back to member functions instead of constructors. Thank you for your help but getting these constructors to work is far more effort than it's worth. – DragonDePlatino Feb 14 '16 at 03:25