Constructors and objects

Evening all,
Im trying to create a class called NoiseLoop but when I try to declare variables into the constructor through the .h file

 float diameter;
    NoiseLoop(float diameter){
       this->diameter = diameter;
    }
    
    private: 

}; 

I get an error in the .cpp file saying “Out-of-line definition of ‘NoiseLoop’ does not match any declaration in ‘NoiseLoop’”
Do I need to pass a variable through private: ?
Its float diameter causing me trouble

#include "NoiseLoop.h"
NoiseLoop::NoiseLoop(){
    
}

Im guessing its to do with float diameter not being referenced in the .cpp

Thanks in advanced

NoiseLoop .h file


#ifndef _NoiseLoop // if this class hasn't been defined, the program can define it
#define _NoiseLoop // by using this if statement you prevent the class to be called more than once which would confuse the compiler
#include "ofMain.h" // we need to include this to have a reference to the openFrameworks framework
class NoiseLoop {

    public: // place public functions or variables declarations here

    // methods, equivalent to specific functions of your class objects
    void setup();    // setup method, use this to setup your object's initial state
    void update();  // update method, used to refresh your objects properties
    void draw();    // draw method, this where you'll do the object's drawing

    // variables
   
    
    float diameter;
    NoiseLoop(float diameter){
       this->diameter = diameter;
    }
    
    private: // place private functions or variables declarations here

}; // don't forget the semicolon!


#endif /* NoiseLoop_h */

.cpp file

//
//  NoiseLoop.cpp
//  noiseyCircThree
//
//  Created by chris courage on 13/12/2020.
//

#include "NoiseLoop.h"
NoiseLoop::NoiseLoop(){
    
}



void NoiseLoop::setup(){
    
    
}



void NoiseLoop::update(){
    
    
}




void NoiseLoop::draw(){
    
    
}





Why are you doing definition of class two times ?
here : NoiseLoop(float diameter){ this->diameter = diameter; }
You don’t need to define twice ! Just decide where you want to do your definition in header or cpp file.
For example you ca do this:

// .h
NoiseLoop(float diameter);
//cpp
NoiseLoop::NoiseLoop(float diameter){
    this->diameter = diameter;
}
1 Like

Hi,

In .cpp you have:

NoiseLoop::NoiseLoop(){
}

1- This is a definition: you are writing the constructor body (between the braces), the code that define this constructor (what does it do ?).
You have not written anything between the braces, but still, this is a constructor definition. You are asking the compiler to create a constructor, a piece of code to execute, that doesn’t do anything.
If the compiler do what you’re asking, you will be able to write elsewhere:

NoiseLoop aLoop;

and the program will then execute the empty constructor you’ve defined, to create the aLoop instance.

2- This definition is in .cpp
So this is called an out-of-line definition (opposite to an inline definition, directly in the .h class body)

3- You are allowed to define the constructor in .cpp only if you previously declare it in .h
But in .h you don’t have any declaration like this:

NoiseLoop();

You have not declared a constructor with no arguments.

This is why you’ve got this error message:

Out-of-line(2) definition(1) of ‘NoiseLoop’ does not match any declaration(3) in ‘NoiseLoop’

Instead, in .h, you’ve got the inline definition of a constructor that takes one float argument (diameter).

class NoiseLoop {
    public:
    float diameter;
    NoiseLoop(float diameter){
        this->diameter = diameter;
    }
}

With this .h you declare and define the constructor at the same time. This is enough. You can now create NoiseLoop instance like that:

NoiseLoop aLoop(10.f);

And you can delete the

NoiseLoop::NoiseLoop(){ 
}

from the .cpp, the compilation error will disappear.

You can also declare the constructor in .h and define it in .cpp, like @Dorald said.

If you want to have 2 constructors, one with an argument, and the other without argument, this is also possible, in this case you will need to declare and define both of them.
Inline:

// .h
    float diameter = 10.f; // better to initialize the diameter if we have
                           // a constructor with no args
    // 1rst constructor declaration and definition
    NoiseLoop(){}
    // 2nd constructor declaration and definition
    NoiseLoop(float diameter){
       this->diameter = diameter;
    }

Or out-of-line:

// .h
    float diameter = 10.f;
    // 1rst constructor declaration
    NoiseLoop();
    // 2nd constructor declaration
    NoiseLoop(float diameter);
// .cpp
// 1rst constructor definition
NoiseLoop::NoiseLoop(){
}
// 2nd constructor definition
NoiseLoop::NoiseLoop(float diameter){
    this->diameter = diameter;
}
2 Likes

Im attempting to translate the Processing method of classes to OFX plus synthesis the OFX OOPS example. I have been iterating through develping a workflow without too much success. Just line by line testing.

I did managed to clear the error following your method, thanks.

Here is the workflow I know so far, feel free to add notes:

//NoiseLoop.h

    //declare class
    //class name
    
    // place public functions or variables declarations here

    // methods, equivalent to specific functions of your class objects


    // variables


    //constructor - Define here ex. NoiseLoop(float diameter);
    //    or define in cpp and define parameters


//NoiseLoop.cpp


//ofApp.h
    //call object and assign it a name ex NoiseLoop xNoise

//ofApp.cpp
    //run objet and pass in paramters


What is the better method for defining the parameters, in the .h or the .cpp?

Great, this is v.helpful :slight_smile:

This is the information and examples I have been seeking to work through transposing a PROCESSING sketch into OFX.

Ive not found any example workflows for creating an object from scratch, and editing previous examples gets messy.

BUT I will continue, thanks!

Ive created notes for developing the workflow, please feel free to add/adjust any information thats needed.

//NoiseLoop.h

    //declare class
    //class name
    
    // place public functions or variables declarations here

    // methods, equivalent to specific functions of your class objects


    // variables


    //constructor - Define here ex. NoiseLoop(float diameter);
    //    or define in cpp and define parameters


//NoiseLoop.cpp


//ofApp.h
    //call instance of object and assign it a name ex NoiseLoop xNoise

//ofApp.cpp
    //run instance of object and pass in paramters


Many thanks

yeh, didnt go so well
heres the code from processing:

class NoiseLoop {
  float diameter;
  float min, max;
  float cx;
  float cy;

  NoiseLoop(float diameter, float min, float max) {
    this.diameter = diameter;
    this.min = min;
    this.max = max;
    cx = random(1000);
    cy = random(1000);
  }

  float value(float a) {
    float xoff = map(cos(a), -1, 1, cx, cx + diameter);
    float yoff = map(sin(a), -1, 1, cy, cy + diameter);
    float r = noise(xoff, yoff);
    return map(r, 0, 1, min, max);
  }
}

can I just do this in .h?
If I were to guess I would say the OF functions probably need to be declared in .cpp and not here?

 // variables
    ofColor color;  // color using ofColor type
    float diameter;
     float min, max;
     float cx;
     float cy;

    NoiseLoop(float diameter, float min, float max) {
        this->diameter = diameter;
        this->min = min;
        this->max = max;
        cx = ofRandom(1000);
        cy = ofRandom(1000);
      }

      float value(float a) {
        float xoff = ofMap(cos(a), -1, 1, cx, cx + diameter);
        float yoff = ofMap(sin(a), -1, 1, cy, cy + diameter);
        float r = ofNoise(xoff, yoff);
        return ofMap(r, 0, 1, min, max);
      }
    
    
    private: // place private functions or variables declarations here

}; // don't forget the semicolon!

then make my instances in the .h

 NoiseLoop xNoise;
 NoiseLoop yNoise;

checked to see if it compiles and get this

Call to implicitly-deleted default constructor of ‘ofApp’

Yes, you can do that, but I’m not sure you should do :slight_smile: (probably not)

C++ allows to define the classes methods (and constructors that are special methods) in multiple places.
The basis is to declare the methods in .h, and to define them in .cpp

I think you have to learn more about C++, if you want to use classes. I recommend you to find some general C++ tutorial, lesson, book about classes and POO in C++.
OF is C++ framework, so you have to learn some C++.
OF is like a stranger co-worker. If you want him to do what you want, you have to learn his language, the C++.
You can start with only some basic C++ notion. You can achieve what you are coding without classes. But you will have to learn more as you want to do more complicated stuffs. Here you want to use OOP, classes, objects, so you must learn how it works in C++.
Sorry, I have no tutorials recommendations because I already known about coding and OOP when I’ve started to use C++. Perhaps check these topics:


Anyway, this is how you define the methods (and constructor) in the .cpp:

.h

class NoiseLoop {
public:
    ofColor color;
    float diameter;
    float min, max;
    float cx;
    float cy;

    NoiseLoop(float diameter, float min, float max);
    float value(float a);
};

.cpp

#include "NoiseLoop.h"

NoiseLoop::NoiseLoop(float diameter, float min, float max) {
        this->diameter = diameter;
        this->min = min;
        this->max = max;
        cx = ofRandom(1000);
        cy = ofRandom(1000);
}
float NoiseLoop::value(float a) {
        float xoff = ofMap(cos(a), -1, 1, cx, cx + diameter);
        float yoff = ofMap(sin(a), -1, 1, cy, cy + diameter);
        float r = ofNoise(xoff, yoff);
        return ofMap(r, 0, 1, min, max);
}

I’ve missed this part of your last post:

Like I said before:

NoiseLoop xNoise;

ask to create a new NoiseLoop instance, and to use a constructor that takes no arguments. You only have defined a constructor that takes 3 floats as arguments, so you can only do things like:

NoiseLoop xNoise(15.f, 30.f, 40.f);

This will use the NoiseLoop(float diameter, float min, float max) constructor.
You definitively need some more C++ background.

1 Like

Great, thanks so much for taking the time to explain these things.

Yes I more c++ experience is a must and coming from a processing background makes it frustrating and of course just want to jump in at the deep end. I am / will read more and develop my c++ as you said it is the basis of the OFX framework.
All this work is for my MA project in Jan, just trying to go above and beyond the basics.

Many thanks, will update once its done.

I have found this which walks through OOP.
It makes sense to me and I understand the workflow BUT…
The reason I kept writing NoiseLoop xNoise;was because I kept getting this error EXPECTED ‘)’
when I wrote NoiseLoop xNoise(5,0,700);

Can you show more code, to be sure ?

I did manage to get my object and instance to work but I had to create the instance in ofAPP.cpp in the draw function. This code below works and I create a particle with xNoise and yNoise instances

void ofApp::draw(){
    //phase = ofGetFrameNum();
    NoiseLoop xNoise(1,0,ofGetWidth());
    NoiseLoop yNoise(1,0,ofGetHeight());
    cout << xNoise.diameter << " " << xNoise.cx  << " " << yNoise.cy << " " << xNoise.value(a)<< " " << yNoise.value(a) <<"\n";


  
//    float a = phase;
    float x = xNoise.value(a);
    float y = yNoise.value(a);
    cout<<a<<endl;
    ofDrawCircle(x, y, 100);
    
    a+=0.01;
   
}

//.cpp
NoiseLoop::NoiseLoop (float diameter, float min, float max) {
    this->diameter = diameter;
    this->min = min;
    this->max = max;
    cx = ofRandom(1000);
    cy = ofRandom(1000);
    
  }

float NoiseLoop::value(float a){
    float xoff = ofMap(cos(a), -1, 1, 0, diameter);
    float yoff = ofMap(sin(a), -1, 1, 0, diameter);
    float r = ofNoise(xoff, yoff);
    return ofMap(r, 0, 1, min, max);
}

Following on the issue of the instance created in the draw function is that when I add float cx and float cy are being constantly updated.

//ofAPP.cpp
void ofApp::draw(){
    //phase = ofGetFrameNum();
    NoiseLoop xNoise(1,0,ofGetWidth());
    NoiseLoop yNoise(1,0,ofGetHeight());
    cout << xNoise.diameter << " " << xNoise.cx  << " " << yNoise.cy << " " << xNoise.value(a)<< " " << yNoise.value(a) <<"\n";


 
    float x = xNoise.value(a);
    float y = yNoise.value(a);
    cout<<a<<endl;
    ofDrawCircle(x, y, 100);
    
    a+=0.01;

//.cpp
float NoiseLoop::value(float a){
    float xoff = ofMap(cos(a), -1, 1, cx, cx+  diameter);
    float yoff = ofMap(sin(a), -1, 1, cy, cy+  diameter);
    float r = ofNoise(xoff, yoff);
    return ofMap(r, 0, 1, min, max);
}

In processing the instances xNoise and yNoise are global and the parameters(incu cx/cy) would be declared once by calling the class in setup.
If I create the instances in the .h I get an error “Expected ')” '“Expected parameter declarator”

#pragma once

#include "ofMain.h"
#include "NoiseLoop.h"
#include "Ball.h"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();
		void keyPressed(int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
    void render(float percent);
    Boolean randomValue;
    float noiseMax;
    float phase;
    float a;
    NoiseLoop xNoise(1,0,600);
    NoiseLoop yNoise(1,0,600);

and for reference here is the object.cpp

NoiseLoop::NoiseLoop (float diameter, float min, float max) {
    this->diameter = diameter;
    this->min = min;
    this->max = max;
    cx = ofRandom(1000);
    cy = ofRandom(1000);
    
  }

float NoiseLoop::value(float a){
    float xoff = ofMap(cos(a), -1, 1, cx, cx+  diameter);
    float yoff = ofMap(sin(a), -1, 1, cy, cy+  diameter);
    float r = ofNoise(xoff, yoff);
    return ofMap(r, 0, 1, min, max);
}

I think the reason my particle is so erratic is due to the cx/cy call every frame instead of once in set up.

    cx = ofRandom(1000);
    cy = ofRandom(1000);

So to conclude XD
I want to call my instances in setup run the constructor Noiseloop but in the draw function pass a into float NoiseLoop::value(float a) into the draw loop.

 float x = xNoise.value(a);
    float y = yNoise.value(a);
    cout<<a<<endl;
    ofDrawCircle(x, y, 100);
    
    a+=0.01;

Thanks again

There is something tricky I haven’t wrote before (in fact I had forgotten it): you can’t write NoiseLoop xNoise( 1, 0, 600 ); to declare and initialize a class member in a header file (.h). You have to write:

NoiseLoop xNoise = NoiseLoop( 1, 0, 600 ) ;

This should solve your problem, because you’re right, the erratic behavior is due to the constant re-initialization of the NoiseLoop in the draw function.

But I think there is better to do. C++ has evolved a lot since its creation. They’ve introduced with C++11 a new way to initialize the objects, called the Brace-Initialization. I’ve read that this is an attempt to overcome the problems of C++03 initialization by introducing a universal initialization notation that applies to every type. In your case, this is:

NoiseLoop xNoise{ 1, 0, 600 };

More about the brace initialization here.
To use the brace initialization most of the time may be a good practice. But apparently this is not a consensus.

Working example:
src.zip (1,1 Ko)

1 Like

This is great thanks