Problem with 2 classes and implementation

Hi guys, I am getting some strange errors when trying to compile my project. The project consists (at the moment) of a car class and a parking meter class.

Building target ParkingProgram of project ParkingProgram with configuration Release  (2 errors)
          cd /Users/***/ParkingProgram
    /Developer/usr/bin/g++-4.0 -o /Users/***/ParkingProgram/build/ParkingProgram.build/Release/ParkingProgram.build/Objects-normal/ppc/ParkingProgram -L/Users/***/ParkingProgram/build/Release -F/Users/***/ParkingProgram/build/Release -filelist /Users/***/ParkingProgram/build/ParkingProgram.build/Release/ParkingProgram.build/Objects-normal/ppc/ParkingProgram.LinkFileList -arch ppc -mmacosx-version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk
Undefined symbols:
  "ParkedCar::ParkedCar()", referenced from:
      _main in program2.o
  "ParkingMeter::ParkingMeter()", referenced from:
      _main in program2.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
              "ParkedCar::ParkedCar()", referenced from:
                  _main in program2.o
              "ParkingMeter::ParkingMeter()", referenced from:
                  _main in program2.o
            ld: symbol(s) not found
            collect2: ld returned 1 exit status
Build failed (2 errors)

Thanks for the help. Here are my implementations.
parkingmeter.cpp
 
#include <iostream>
#include "ParkingMeter.h"
 
 
 
int ParkingMeter::getTime()
{
        return timePurchased;
}
 
void ParkingMeter::setTime(int time)
{
        timePurchased = time;
}
 
parkedcar.h
 
#ifndef PARKEDCAR_H
#define PARKEDCAR_H
 
class ParkedCar
{
        private:
                char make[30];
                char model[30];
                char color[30];
                int licenceNumber;
                int minutesParked;
        public:
                ParkedCar();
                ParkedCar(const char* make1, const char* model1, const 
                char* color1, int licenceNumber1, int minutesParked1);
                const char* getMake();
                const char* getModel();
                const char* getColor();
                int getLicenceNumber();
                int getMinutesParked();
                void setMake(const char * make1);
                void setModel(const char* model);
                void setColor(const char* color);
                void setLicence(int licenceNumber);
                void setMinutes(int minutesParked); 
};
#endif          
 
parkedcar.cpp
 
#include <iostream>
#include "ParkedCar.h"
 
const char* ParkedCar::getMake()
{
        return make;
}
 
const char* ParkedCar::getModel()
{
        return model;
}
 
const char* ParkedCar::getColor()
{
        return color;
}
 
int ParkedCar::getLicenceNumber()
{
        return licenceNumber;
}
 
int  ParkedCar::getMinutesParked()
{
        return minutesParked;
}
void ParkedCar::setMake(const char* make1)
{
        strcpy(make,make1);
}
void ParkedCar::setModel(const char* model1)
{
        strcpy(model,model1);
}
void ParkedCar::setColor(const char* color1)
{
        strcpy(color,color1);
}
void ParkedCar::setLicence(int licenceNumber1)
{
        licenceNumber = licenceNumber1;
}
void ParkedCar::setMinutes(int minutesParked1)
{
        minutesParked = minutesParked1;
}
        
parkingmeter.h
 
#ifndef PARKINGMETER_H
#define PARKINGMETER_H
 
class ParkingMeter
{
        private:
                int timePurchased;
        public:
                ParkingMeter();
                ParkingMeter(int timePurchased);
                void setTime(int time);
                int getTime();
                
};
#endif
 
 
program2.cpp
 
#include <iostream>
#include "ParkedCar.h"
#include "ParkingMeter.h"
 
using namespace std;
 
int main()
{
        ParkedCar car1;
        ParkingMeter meter1;
        meter1.setTime(100);
        cout << meter1.getTime() << endl;
        car1.setMake("Ford");
        car1.setModel("Taurus");
        car1.setColor("Maroon");
        car1.setLicence(1337);
        car1.setMinutes(25);
        cout << car1.getMake() << endl;
        cout << car1.getModel() << endl;
        cout << car1.getColor() << endl;
        cout << car1.getLicenceNumber() << endl;
        cout << car1.getMinutesParked() << endl;        
}

Open in new window

pacman32689Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
Well, you are declaring both default constructors ( "ParkedCar::ParkedCar()" and  "ParkingMeter::ParkingMeter()") in both header files, yet you aren't providing an implementation in the respective .cpp files. Just add them:
ParkingMeter::ParkingMeter()
{
  // functionality goes here
}
 
ParkedCar::ParkedCar()
{
  // functionality goes here
}

Open in new window

0
Infinity08Commented:
Same for the other undefined constructors :

        ParkedCar::ParkedCar(const char* make1, const char* model1, const char* color1, int licenceNumber1, int minutesParked1)
        ParkingMeter::ParkingMeter(int timePurchased)

You need to implement those too ...
0
pacman32689Author Commented:
Sorry guys, have been sick all day, thanks for pointer! I will get to working on it.
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

itsmeandnobodyelseCommented:
To add to above information:

The constructor was used to initialize and/or set the member variables. You best do that by using an initializer list like that:


ParkedCar::ParkedCar()
    :  licenseNumber(0), minutesParked(0)
{
       make[0] = '\0';
       model[0] = '\0';
       color[0] = '\0';

Some remarks to that:

- if you would omit the constructor in the header, the compiler automatically would create one.
- however, the default constructor wouldn't set your C-type member variables to a well-defined initial value
- that's why you need a implementation for all constructors that explicitly sets all members
- setting the first byte of a char array to zero char makes the char array an empty string
- you better would use std::string instead of char arrays

#include <string>

....
class ParkedCar
{
        private:
                std::string make;
                std::string model;
                std::string color;

Then, the members were initialized automatically. You have no limitation for the length and you easily can assign values:

     model = "Firebird";
     color   = "silver";

- when turning the char arrays to std::string, the second constructor could be the same as you already have and the implementation was made by initializer list only:

ParkedCar::ParkedCar(const char* make1, const char* model1, const
                char* color1, int licenceNumber1, int minutesParked1)  
      : make(make1), model(model1), color(color1),
        licenceNumber(licenceNumber1), minutesParked(minutesParked1)
{
}

That works, cause std::string - like each string class - takes a const char* for one of its constructors.

With the above you would have

int main()
{
        ParkedCar car1("Ford", "Taurus", "Maroon", "1234", 100);
        ...

and could omit all the set functions.

Regards, Alex


0
pacman32689Author Commented:
I am getting some unfamiliar errors like assignment of read-only location. This is my first time using const char pointers, so maybe I am missing something obvious :)
#include <iostream>
#include "ParkedCar.h"
 
ParkedCar::ParkedCar()
{
	make[0] = '\0';
	model[0] = '\0';
	color[0] = '\0';
	licenceNumber = 0;
	minutesParked = 0;
}
ParkedCar::ParkedCar(const char* make1, const char* model1, const char* color1, int licenceNumber1, int minutesParked1)
{
	strcpy(make,make1);
	strcpy(model,model1);
	strcpy(color,color1);
	licenceNumber = licenceNumber1;
	minutesParked = minutesParked1;
}
const char* ParkedCar::getMake()
{
	return make;
}
 
const char* ParkedCar::getModel()
{
	return model;
}
 
const char* ParkedCar::getColor()
{
	return color;
}
 
int ParkedCar::getLicenceNumber()
{
	return licenceNumber;
}
 
int  ParkedCar::getMinutesParked()
{
	return minutesParked;
}
void ParkedCar::setMake(const char* make1)
{
	strcpy(make,make1);
}
void ParkedCar::setModel(const char* model1)
{
	strcpy(model,model1);
}
void ParkedCar::setColor(const char* color1)
{
	strcpy(color,color1);
}
void ParkedCar::setLicence(int licenceNumber1)
{
	licenceNumber = licenceNumber1;
}
void ParkedCar::setMinutes(int minutesParked1)
{
	minutesParked = minutesParked1;
}
	

Open in new window

0
pacman32689Author Commented:
above is ParkedCar.cpp
0
pacman32689Author Commented:
another error is unitialized member 'ParkedCar::make'

ect. with all my char arrays
0
pacman32689Author Commented:
Sorry to bump, but I can't understand what is going on. It is telling me my const char arrays are being uninitialized, which I don't quite understand.
0
Infinity08Commented:
>> assignment of read-only location.

Did you make the class members const char* instead of char* ? const char* means that the string cannot be modified. For example, you can't do :

        strcpy(str1, str2);

if str1 is a const char*


>> unitialized member 'ParkedCar::make'

This is probably related to the previous error.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
itsmeandnobodyelseCommented:
>>> class ParkedCar
>>> {
>>>         private:
>>>                 char make[30];
>>>                 char model[30];
>>>                 char color[30];

With that you wouldn't get the error 'assignment of read-only location' as the char aarays are not read-only but writeable.

>>> class ParkedCar
>>> {
>>>         private:
>>>                 const char* make;

But if you turned the member types to const char* these members were const and thus read-only. Then, statements like

     strcpy(make, make1);

would have two errors. First, you try to write to a const member. Second, the pointer wasn't initialized and the pointer was invalid (was not pointing to allocated memory).

 
0
itsmeandnobodyelseCommented:

// .h

....
class ParkedCar
{
        private:
              char make[30];
              char model[30];
              char color[30];
....

// .cpp

ParkedCar::ParkedCar(const char* make1, const char* model1, const char* color1, int licenceNumber1, int minutesParked1)
    : licenceNumber(licenceNumber1)
    , minutesParked(minutesParked1)
{
       int len = sizeof(make) - 1;
       strncpy(make, make1, len);
       make[len] = '\0';
       len = sizeof(model) - 1;
       strncpy(model, model1, len);
       model[len] = '\0';
       len = sizeof(color) - 1;
       strncpy(color, color1, len);
       color[len] = '\0';
}

That looks rather bad, doesn't it? But actually it is the only way out to make fixed sized char arrays safe.

Using std::string for the text members it simply was:

ParkedCar::ParkedCar(const char* make1, const char* model1, const
                char* color1, int licenceNumber1, int minutesParked1)  
      : make(make1)
      , model(model1)
      , color(color1)
      , licenceNumber(licenceNumber1)
      , minutesParked(minutesParked1)
{
}


0
pacman32689Author Commented:
Thanks guys, fixed it a bit ago. Awarding points.
0
pacman32689Author Commented:
thanks
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.