7

So I was working on my code, which is designed in a modular way. Now, one of my classes; called Splash has to create a object of another class which is called Emitter. Normally you would just create the object and be done with it, but that doesn't work here, as the Emitter class has a custom constructor. But when I try to create an object, it doesn't work.

As an example;

Emitter has a constructor like so: Emitter::Emitter(int x, int y, int amount); and needs to be created so it can be accessed in the Splash class.

I tried to do this, but it didn't work:

class Splash{
    private:
        Emitter ps(100, 200, 400, "firstimage.png", "secondimage.png"); // Try to create object, doesn't work.
    public:
       // Other splash class functions.
}

I also tried this, which didn't work either:

class Splash{
    private:
        Emitter ps; // Try to create object, doesn't work.
    public:
       Splash() : ps(100, 200, 400, "firstimage.png", "secondimage.png")
       {};
}

Edit: I know the second way is supposed to work, however it doesn't. If I remove the Emitter Section, the code works. but when I do it the second way, no window opens, no application is executed.

So how can I create my Emitter object for use in Splash?

Edit:

Here is my code for the emitter class and header: Header

// Particle engine for the project

#ifndef _PARTICLE_H_
#define _PARTICLE_H_

#include <vector>
#include <string>
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "image.h"

extern SDL_Surface* gameScreen;

class Particle{
    private: // Particle settings
        int x, y;
        int lifetime;
    private: // Particle surface that shall be applied
        SDL_Surface* particleScreen;
    public: // Constructor and destructor
        Particle(int xA, int yA, string particleSprite);
        ~Particle(){};
    public: // Various functions
        void show();
        bool isDead();
};

class Emitter{
    private: // Emitter settings
        int x, y;
        int xVel, yVel;
    private: // The particles for a dot
        vector<Particle> particles;
        SDL_Surface* emitterScreen;
        string particleImg;
    public: // Constructor and destructor
        Emitter(int amount, int x, int y, string particleImage, string emitterImage);
        ~Emitter();
    public: // Helper functions
        void move();
        void show();
        void showParticles();
};

#endif

and here is the emitter functions:

#include "particle.h"

// The particle class stuff
Particle::Particle(int xA, int yA, string particleSprite){
    // Draw the particle in a random location about the emitter within 25 pixels    
    x = xA - 5 + (rand() % 25);
    y = yA - 5 + (rand() % 25);
    lifetime = rand() % 6;
    particleScreen = Image::loadImage(particleSprite);
}

void Particle::show(){
    // Apply surface and age particle
    Image::applySurface(x, y, particleScreen, gameScreen);
    ++lifetime;
}

bool Particle::isDead(){
    if(lifetime > 11)
        return true;
    return false;
}

// The emitter class stuff

Emitter::Emitter(int amount, int x, int y, string particleImage, string emitterImage){
    // Seed the time for random emitter
    srand(SDL_GetTicks());
    // Set up the variables and create the particles
    x = y = xVel = yVel = 0;
    particles.resize(amount, Particle(x, y, particleImage));
    emitterScreen = Image::loadImage(emitterImage);
    particleImg = particleImage;
}

Emitter::~Emitter(){
    particles.clear();
}

void Emitter::move(){
}

void Emitter::show(){
    // Show the dot image.
    Image::applySurface(x, y, emitterScreen, gameScreen);
}

void Emitter::showParticles(){
    // Go through all the particles
    for(vector<Particle>::size_type i = 0; i != particles.size(); i++){
        if(particles[i].isDead() == true){
            particles.erase(particles.begin() + i);
            particles.insert(particles.begin() + i, Particle(x, y, particleImg));
        }
    }
    // And show all the particles
    for(vector<Particle>::size_type i = 0; i != particles.size(); i++){
        particles[i].show();
    }
}

Also here is the Splash Class and the Splash Header.

Rivasa
  • 6,510
  • 3
  • 35
  • 64

2 Answers2

11

The second option should work, and I would start looking at compilation errors to see why it doesn't. In fact, please post any compilation errors you have related to this code.

In the meantime, you can do something like this:

class Splash{
   private:
     Emitter* ps;
   public:
     Splash() { ps = new Emitter(100,200,400); }
     Splash(const Splash& copy_from_me) { //you are now responsible for this }
     Splash & operator= (const Splash & other) { //you are now responsible for this}

     ~Splash() { delete ps; }

};
Jonathan Henson
  • 8,076
  • 3
  • 28
  • 52
  • 2
    could you elaborate on why this would help? – juanchopanza Aug 07 '12 at 19:40
  • @juanchopanza It should compile, work, and do what he needs. However, my guess is that it still will not work because the problem with his code is not with the code he posted but with something else either in the Emitter class. Either way, this will reveal the problem. – Jonathan Henson Aug 07 '12 at 19:43
  • Hmm, i'll post the emitter class. – Rivasa Aug 07 '12 at 19:45
  • 3
    Following the advice of using a pointer may introduce additional problems instead of fixing things. In particular, the given code violates the rule of three. I.e., it will do unholy things if any instance of `Splash` is ever copied. – Cheers and hth. - Alf Aug 07 '12 at 19:45
  • @Cheersandhth.-Alf Yes it does, I never claimed this as production code, and intend that the author knows how to write basic code. If it would make you happy, I can add a copy constructor and assignment operator. :) – Jonathan Henson Aug 07 '12 at 19:49
  • +1, and accepted, changed my stuff to folly the rule of three. – Rivasa Aug 08 '12 at 15:03
  • @Pototo I wasn't suggesting someone use dynamic memory, only that this would help the OP find the problem easier. – Jonathan Henson Jul 29 '16 at 20:40
  • Right. I understand. – Pototo Aug 01 '16 at 17:10
0

Well, I managed to fix it, in a hackish way though. What I did was create a default constructor, and move my normal Constructor code into a new function. Then I created the object and called the the new init function to set everything up.

Rivasa
  • 6,510
  • 3
  • 35
  • 64
  • 2
    This indicates a bug in your code. I see you have a destructor but no copy-constructor or assignment operator, are you following the [Rule of Three](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three)? Don't create hacks, create fixes. – GManNickG Aug 07 '12 at 20:34
  • The copy-constructor is not needed for my splash class, as only 1 is made at the start of the program, then destroyed. Also the destructor for the splash class is just the default one. – Rivasa Aug 07 '12 at 20:38
  • 1) If it's not needed, delete it (C++11) or declare but don't define it (C++03). 2) Okay, but never write out a destructor unless you intend to add custom behavior, let the compiler do it. – GManNickG Aug 07 '12 at 20:43
  • You could also just make the copy constructor and assignment operator private and give it an empty definition. That way anyone using the class will receive a compiler error when trying to do a copy or assignment. – Jonathan Henson Aug 07 '12 at 21:48