I have a class project that I did from college that "works", but isn't constructed properly.
It has a Date class and a Person class.
In my "working" code, all of the class data (constructors, members, and functions) are contained within a single header file for each class (a separate file for each class).
The program loads text file data (Persons, presidents and actors) into a vector, sorts, filters and prints the data on the console, and saves it to a file.
In the Person class constructor (and functions), the Date class is instantiated for a "birthdate" object. Then the birthday is used in the program.
The problem I'm having is this:
I can easily instantiate "Date" in the Person constructor and members, if all the class code is in a header file for each class, AND I make the Date the "Parent" class for Person. But if I don't do both of these things, then "Person" doesn't know anything about "Date" and cannot instantiate anything from Date.
If I use an #include "Date.h" in Person.h, this creates even more problems and doesn't work either.
Of course, "Date" is not a proper parent class for "Person", but it was the only way I could hack the code to make it work lol. When I first coded this years ago in college, I never did figure out how to divide the class code properly in so that it would compile and run. The "working code" with all the class code in a header file is my hack. I want to learn how to do it the right way.
I have pasted in the bare minimum example below of what "works" and what doesn't. Any tips to make this code work with the classes divided into header and .cpp files would be much appreciated.
class Date {
private:
int month;
int day;
int year;
public:
Date::Date() {}
virtual ~Date() {}
Date( int aMonth, int aDay, int aYear ) {
this->month = aMonth;
this->year = aYear;
this->day = aDay;
}
// "Getter" functions for the Date class
int getMonth(){return this->month;}
int getYear() {return this->year;}
int getDay() {return this->day;}
// "Setter" functions for the Date class
void setDay( int aDay ){ this->day = aDay; }
void setMonth( int aMonth ) { this->month = aMonth; }
void setYear( int aYear ) { this->year = aYear; }
};
class Person : public Date{
private:
string title;
string firstName;
string lastName;
Date birthDate;
public:
Person::Person() {}
Person(string title, string firstName, string lastName, Date birthDay);
virtual ~Person() {}
//"Getter" functions for the Person class
string getTitle() { return title; }
string getFirstName() { return firstName; }
string getLastName() { return lastName; }
Date getBirthDay() { return birthDate; }
//"Setter" functions for the Person class
void setTitle(string Title) { this->title = Title; }
void setFirstName(string fName) { this->firstName = fName; }
void setLastName (string lName) { this->lastName = lName; }
void setBirthday (Date aBirthday) { this->birthDate = aBirthday; }
};
Date.h
class Date {
private:
int month;
int day;
int year;
public:
Date();
virtual ~Date() {}
Date( int aMonth, int aDay, int aYear );
//Getters and setters
int getMonth();
int getYear() ;
int getDay();
void setDay( int aDay );
void setMonth( int aMonth ) ;
void setYear( int aYear ) ;
};
Date.cpp
#include "Date.h"
Date::Date() {}
Date::Date( int aMonth, int aDay, int aYear ) {
this->month = aMonth;
this->year = aYear;
this->day = aDay;
}
int Date::getMonth(){return this->month;}
int Date::getYear() {return this->year;}
int Date::getDay() {return this->day;}
//"Setter" functions for the Date class
void Date::setDay( int aDay ){ this->day = aDay; }
void Date::setMonth( int aMonth ) { this->month = aMonth; }
void Date::setYear( int aYear ) { this->year = aYear; }
Person.h
#include <string>
class Person{
private:
string title;
string firstName;
string lastName;
Date birthDate;
public:
//Person::Person() {}
Person(string title, string firstName, string lastName, Date birthDay);
//"Getter" functions for the Person class
string getTitle() { return title; }
string getFirstName() { return firstName; }
string getLastName() { return lastName; }
Date getBirthDay() { return birthDate; }
//"Setter" functions for the Person class
void setTitle(string Title) { this->title = Title; }
void setFirstName(string fName) { this->firstName = fName; }
void setLastName (string lName) { this->lastName = lName; }
void setBirthday (Date aBirthday) { this->birthDate = aBirthday; }
};
Person.cpp
#include "Person.h"
#include <iostream>
using namespace std;
//Person class constructor with 0 arguments
Person::Person(string atitle, string afirstName, string alastName, Date abirthDay) {
title = atitle,
firstName = afirstName,
lastName = alastName,
birthday = abirthDay)
}
//"Getter" functions for the Person class
string Person::getTitle() { return title; }
string Person::getFirstName() { return firstName; }
string Person::getLastName() { return lastName; }
Date Person::getBirthDay() { return birthDate; }
//"Setter" functions for the Person class
void Person::setTitle(string Title) { this->title = Title; }
void Person::setFirstName(string fName) { this->firstName = fName; }
void Person::setLastName (string lName) { this->lastName = lName; }
void Person::setBirthday (Date aBirthday) { this->birthDate = aBirthday; }
I'm using MS Visual Studio 2012 Update 4 on a Windows 7 PC.
To prevent redefinition errors, add include guards to header files. To be portable, use:
#if !defined(THE_HEADER_NAME_H)
#define THE_HEADER_NAME_H
// Usual code and declarations here.
#endif
In Visual Studio, you can use:
#pragma once
// Usual code and declarations here.
In headers, don't write (at global scope level)
using namespace XXXXX
because that will cause all files including yours to also use namespace XXXXX which they may not want imposed upon them. If you use types that are in a namespace, type out the entire type name with namespace, so use:
std::string getTitle()
(In a cpp file, you can have 'using namespace XXXXX' after any #includes)
You have 2 problems IMHO.
First is the guards problem that Scott Langham's answer will solve.
The second is a problem of namespaces.
I assume that in your working source, you have (directly on indirectly via stdafx.h or another include) :
#include <string>
using namespace std;
It is not recommended to have using namespace std;
in a .h
header file ... but that means that you should use std::string
instead of string
:
date.h
class Date {
private:
int month;
int day;
int year;
public:
Date::Date() { } //Date class constructor with 0 arguments
virtual ~Date() {} //Date class destructor
Date( int aMonth, int aDay, int aYear ) { //Date class constructor with 3 arguments
this->month = aMonth; // Set the private member data with the argument data
this->year = aYear;
this->day = aDay;
}
//"Getter" functions for the Date class
int getMonth(){return this->month;}
int getYear() {return this->year;}
int getDay() {return this->day;}
//"Setter" functions for the Date class
void setDay( int aDay ){ this->day = aDay; }
void setMonth( int aMonth ) { this->month = aMonth; }
void setYear( int aYear ) { this->year = aYear; }
};
person.h (string -> std::string and remove method implementations)
#include <string>
#include "Date.h"
class Person : public Date{
private: //Private data members
std::string title;
std::string firstName;
std::string lastName;
Date birthDate;
public:
Person::Person() {} //Person class constructor with 0 arguments
Person(std::string title,
std::string firstName,
std::string lastName,
Date birthDay); //Person class constructor with 4 arguments
virtual ~Person(){} //Person class destructor
//"Getter" functions for the Person class
std::string getTitle();
std::string getFirstName();
std::string getLastName();
Date getBirthDay();
//"Setter" functions for the Person class
void setTitle(std::string Title);
void setFirstName(std::string fName);
void setLastName (std::string lName);
void setBirthday (Date aBirthday);
};
person.cpp (fixed includes and constructor)
#include <string>
#include "Person.h"
#include <iostream>
using namespace std;
//Person class constructor with 0 arguments
Person::Person(string atitle, string afirstName, string alastName, Date abirthDay) {
title = atitle,
firstName = afirstName,
lastName = alastName,
birthDate = abirthDay;
}
//"Getter" functions for the Person class
string Person::getTitle() { return title; }
string Person::getFirstName() { return firstName; }
string Person::getLastName() { return lastName; }
Date Person::getBirthDay() { return birthDate; }
//"Setter" functions for the Person class
void Person::setTitle(string Title) { this->title = Title; }
void Person::setFirstName(string fName) { this->firstName = fName; }
void Person::setLastName (string lName) { this->lastName = lName; }
void Person::setBirthday (Date aBirthday) { this->birthDate = aBirthday; }
It can even be used without guards, but guard are anyway a good practice.
In fact as Date.h
is included in Person.h
it should really have a guard - not shown here for simplicity
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.