Go Down

Topic: C++ problem with classes (Read 2 times) previous topic - next topic

Boa

May 24, 2008, 06:05 pm Last Edit: May 24, 2008, 10:56 pm by Boa Reason: 1
Hey there,

I'm doing my first steps in programming with C++. I already succeed in making a class that worked when I wrote a litlle test it. This class is called "Analoog"
Now I want to use objects from this class to make another class, called Licht. I don't know why, but everytime I want to build the librarie he gives errors:
Quote
"Licht.cpp:27: error : '((Licht*)this -> Licht::seconde' does not have class type"

"Licht.cpp:32: error : '((Licht*)this -> Licht::groen' does not have class type"

and

"Licht.cpp:33: error : '((Licht*)this -> Licht::rood' does not have class type"



I'm thinking there's something wrong with the way i'm initialising the class Objects... I tried many things, but everything gave errors.
Does anybody see what I'm doing wrong?

this is the header-file (.h) :

Code: [Select]

/*
Auteur : Bo Knooren
*/
#ifndef Licht_h
#define Licht_h

#include "WConstants.h"

#include <Metro.h>

#include <Analoog.h>

class Licht
{
public:
Licht();
boolean vanGroenNaarRood(int tijd, int aantalStappen);
private:
Analoog groen(int a);
Analoog rood(int b);
Metro seconde(int c); // houdt een 1 bij wanneer 1 seconde is gepasseerd

int counter; // telt de seconden
int teller; // telt de het aantal keer dat de leds een beetje van kleur veranderd zijn
};


#endif





this is the source file (.cpp) :

Code: [Select]

/*
Auteur : Bo Knooren
*/

#include "WProgram.h"
#include "Licht.h"

Licht::Licht()
{
Metro seconde(1000);
Analoog groen(3);
Analoog rood(5);
counter = 0;
teller = 1;
}


/** zal elke keer dat t wordt opgeroepen controleren of het rood en groen moet veranderen en dat dan doen
* tijd in seconden, 85 stappen aangeraden
* veronderstelt dat groen licht al aan is en rood licht uit is
* geeft true als hij klaar is, false als hij nog niet klaar is
*/
boolean Licht::vanGroenNaarRood(int tijd, int aantalStappen)
{
if(aantalStappen > 255) aantalStappen = 255;
if((Metro) seconde.check() == 1) // seconde voorbij?
{
counter++; // seconde bijtellen
if(counter == tijd/aantalStappen*teller) // hit, hij moet veranderen
{
(Analoog) groen.increment(-255/aantalStappen);
(Analoog) rood.increment(255/aantalStappen);
teller++;
}
}

if(counter == tijd) // hij heeft gedaan met faden
{
counter = 0; //counter terug instellen op startwaarde
teller = 1; //teller terug instellen op startwaarde
return true;
}
else return false;
}


simond

This line in your class declaration:
Code: [Select]

Analoog groen(int a);


declares groen to be an instance method taking a single int parameter and returning an instance of class Analoog.

This line, in the class definition:
Code: [Select]

Analoog groen(3);


is a little unusual given the above, I can't even tell what it's really doing, but it looks like you're trying to initialise an instance variable by calling its constructor, in which case you should rewrite the header declaration to read:

Code: [Select]

Analoog groen;  // declare an instance variable of type Analoog.


The same is true for seconde and rood.

Then change the definition of the constructor to read:

Code: [Select]

Licht::Licht()
: seconde(1000), groen(3), rood(5), counter(0), teller(1)
{
}


I suggest you also read up a little more on class declarations, particularly how instance variables and methods are declared and initialised.

Boa

Ok, so  made the chages, i chaged in the header to :

Code: [Select]
class Licht
{
 public:
   Licht();
   boolean vanGroenNaarRood(int tijd, int aantalStappen);
 private:
   Analoog groen;
   Analoog rood;
   Metro seconde;     // houdt een 1 bij wanneer 1 seconde is gepasseerd
   
   int counter;            // telt de seconden
   int teller;             // telt de het aantal keer dat de leds een beetje van kleur veranderd zijn
};


and the constructor of the source to :

Code: [Select]
Licht::Licht(int pinGroen, int pinRood)
: seconde(1000), groen(3), rood(5), counter(0), teller(1)
{
 
}


but it's still giving errors :


Thanks Simond for the respons. Do you know where I can find some literture on declaration and initialation?
the meaning of my class is that a green led is going from on to off while in the same time a red led is going from off to on and this has to take some minutes, but it may not be a loop so you can do other things in the meanwhile. (so no loop with delay)

simond

The order of initialisers in the constructor definition must match the order of members in the class - move Metro seconde to above Analoog groen, and that will take care of the warnings.

The errors are being generated in the body of vanGroenNaarRood(), for which you haven't provided the source.

As far as a good reference is concerned, I would recommend Bruce Eckel's Thinking in C++, and one other book is at work right now and I can't think of the exact title. I'll post a link when I get back to work on Tuesday.

simond


Boa


studioj

Hi, I'm having a similar problem, therefor reusing this thread

I want to use a library i previously created in a new library i'm creating.

in the new library's constructor I call the old library's constructor.

But then I can't use the old library's function in the new library's functions

New library constructor
Code: [Select]
AcceleroDice::AcceleroDice(int sleepPin, int selfTestPin, int zeroGPin, int xPin, int yPin, int zPin, int xOffset, int yOffset, int zOffset)
{
 AcceleroMMA7361 accelero (13, 12, 11, A0, A1, A2, 5, -40, 20);
 ArrayDataAnalyse arrayDataAnalyse;
 int _diceTreshold = 35;
 int _side = 0;
 int _lastSide = 0;
 ...
}


Code: [Select]
int AcceleroDice::getSide()
{
 try
 {
   int i =0;
   while (_j<_average*2)
   {
     _x = accelero.getXAccel();
     _y = accelero.getYAccel();
     _z = accelero.getZAccel();
...

do i have to construct the old libary every time i use the function getSide or is there a way how i can do it only once (and of course if there is such a way is it better to use?)

compiler returned this btw
AcceleroDice.cpp: In member function 'int AcceleroDice::getSide()':
AcceleroDice.cpp:65: error: 'accelero' was not declared in this scope

PaulS

#7
Dec 03, 2010, 04:09 pm Last Edit: Dec 03, 2010, 04:10 pm by PaulS Reason: 1
Code: [Select]
 AcceleroMMA7361 accelero (13, 12, 11, A0, A1, A2, 5, -40, 20);
accelero is a local variable, created in the constructor, with a lifetime that matches the constructor call. Of course you can use it later.

accelero should be a member of the class, and should be initialized in the constructor.

This will most likely require changes to the AcceleroMMA7361 class, to add a no-argument constructor and a begin() method.

The no-argument constructor will be called when you have a statement like
Code: [Select]
AcceleroMMA7361 accelero;
in the AcceleroDice class.

The begin() method would then be called in AcceleroDice::AcceleroDice, like so:
Code: [Select]
accelero.begin(13, 12, 11, A0, A1, A2, 5, -40, 20);

Quote
(and of course if there is such a way is it better to use?)

Yes, it is.

studioj

So, if I'm correct I should call the "AcceleroMMA7361 accelero;" constructor in "int AcceleroDice::getSide()" and in AcceleroDice::AcceleroDice
But do the arguments as sleepPin remain??

PaulS

Quote
So, if I'm correct I should call the "AcceleroMMA7361 accelero;" constructor in "int AcceleroDice::getSide()" and in AcceleroDice::AcceleroDice

You are not.
Code: [Select]
AcceleroMMA7361 accelero;
isn't a function to call.

It is a declaration of a variable accelero, of a specific type, AcceleroMMA7361. As a result of creating that variable, the AcceleroMMA7361::AcceleroMMA7361() function is called, if there is one.

If there is no AcceleroMMA7361::AcceleroMMA7361() function (that is, one that takes no arguments), a compiler error will occur.

As such, the statement goes in the class header file, not in the constructor implementation or the getSide() function implementation.

Quote
But do the arguments as sleepPin remain??

I guess. I don't know what this means, or what of the changes I suggested earlier you implemented.

studioj

I meant the arguments that accelero.begin(...) takes
Will they remain so accelero in getSide still knows the parameters (pin numbers in this case)
Code: [Select]

AcceleroDice::AcceleroDice(int sleepPin, int selfTestPin, int zeroGPin, int xPin, int yPin, int zPin, int xOffset, int yOffset, int zOffset)
{
 AcceleroMMA7361 accelero;
 accelero.begin(13, 12, 11, A0, A1, A2, 5, -40, 20);

PaulS

Quote
Will they remain so accelero in getSide still knows the parameters (pin numbers in this case)

That is up to you to decide, but, changing the order of the pins doesn't seem like a useful thing to do, so I don't suppose that you will.

Code: [Select]
AcceleroDice::AcceleroDice(int sleepPin, int selfTestPin, int zeroGPin, int xPin, int yPin, int zPin, int xOffset, int yOffset, int zOffset)
{
[glow]  AcceleroMMA7361 accelero;[/glow]
 accelero.begin(13, 12, 11, A0, A1, A2, 5, -40, 20);

accelero is STILL a local variable, so you haven't accomplished anything.

studioj

so i should make it a global variable?
or a private member?

PaulS

Quote
so i should make it a global variable?
or a private member?

Global - no.
Member - yes. Private - maybe. Public - maybe.

There are pros and cons to private members. In general, they are preferred for encapsulation, but sometimes it requires more code to manage the private data than is worth the effort. A point class, for instance, with private x, y members, and public getX, getY, setX, and setY methods requires a lot more code than a point class with public x, y members.

studioj

ok I think I got it, thank you very much PaulS
c++ basics are far away after not writing any code for some time :-)

Go Up