C++ Cohesion with class Date - c++

I'm preparing for an exam of c++. In the last test I failed the cohesion between a class that had the Date date_event as a variable.
How to create different constructors of class P if the class P need an object Data to create an object of the class( the one with no parameters, the one with all the parameters and the copy constructor)?
Also i didn't write this Date actual class. Is it correct to write constructors like that ?
How should giorno(0) , month(0) etc work properly ?
(giorno=day, mese=month, anno= year)
#ifndef DATA_H
#define DATA_H
#include <iostream>
#include <cstring>
using namespace std;
class Data{
friend ostream& operator<<(ostream&, const Data&);
friend istream& operator>>(istream&, Data&);
protected:
int giorno;
int mese;
int anno;
public:
Data(): giorno(0), mese(0), anno(0){}
Data(const int& g, const int& m, const int& a): giorno(g), mese(m), anno(a){}
Data(const Data& D) : giorno(D.giorno), mese(D.mese), anno(D.anno){}
//...
};
#include "Data.h"
class P{
protected:
Data birthday;
public:
P();
P(const int, const int, const int); //i should pass day, month, year right?
P(const P&);
}

Well the question is not clear, but several things can be said.
General
Avoid using namespace std; and use the namespace directly. E.g. friend std::ostream& operator<<(std::ostream&, const Data&);
I suppose this is not the original code, but just in case : don't forget your header guards #ifndef CLASSNAME_H, #define CLASSNAME_H & #endif /* CLASSNAME_H */
Date class
You can implement the constructor that way, but prefer implementing them in the .cpp file.
It is unnecessary to pass the integer parameters as references. Use this for big parameters, from strings to whole objects.
Prefer English for code, even if your colleagues/reviewers/professors are not English. It is always preferred in computer science. This is valid for variable/function names, but also for comments.
P(erson) class
Give your parameters names. Often people that will use your code will only read the headers, so the headers must be as self-explanatory as possible.
For the P contractor, try this :
class Date {
public:
Date(const int pDay, const int pMonth, const int pYear);
Date(const Date &pDate);
/* Getters */
int day(void) const;
int month(void) const;
int year(void) const;
/* Setters */
void setDay(const int pDay);
void setMonth(const int pMonth);
void setYear(const int pYear);
protected:
int mDay;
int mMonth;
int mYear;
};
class Person {
public:
Person(const int pDay, const int pMonth, const int pYear);
Person(const Person &pPerson);
/* Getters */
Date birthday(void) const;
/* Setters */
void setBirthday(const int pDay, const int pMonth, const int pYear);
void setBirthday(const Date &pDate);
protected:
Date mBirthday;
};
Date::Date(const int pDay, const int pMonth, const int pYear):
mDay(pDay),
mMonth(pMonth),
mYear(pYear)
{
/* Empty */
}
Date::Date(const Date &pDate) :
mDay(pDate.day()),
mMonth(pDate.month()),
mYear(pDate.year())
{
/* Empty */
}
int Date::day(void) const {
return mDay;
}
int Date::month(void) const {
return mMonth;
}
int Date::year(void) const {
return mYear;
}
/* Setters */
void Date::setDay(const int pDay) {
mDay = pDay;
}
void Date::setMonth(const int pMonth) {
mMonth = pMonth;
}
void Date::setYear(const int pYear) {
mYear = pYear;
}
Person::Person(const int pDay, const int pMonth, const int pYear):
mBirthday(pDay, pMonth, pYear)
{
/* Empty */
}
Person::Person(const Person &pPerson):
mBirthday(pPerson.birthday().day(), pPerson.birthday().month(), pPerson.birthday().year())
{
/* Empty */
}
Date Person::birthday(void) const {
return mBirthday;
}
void Person::setBirthday(const int pDay, const int pMonth, const int pYear) {
mBirthday.setDay(pDay);
mBirthday.setMonth(pMonth);
mBirthday.setYear(pYear);
}
void Person::setBirthday(const Date &pDate) {
mBirthday.setDay(pDate.day());
mBirthday.setMonth(pDate.month());
mBirthday.setYear(pDate.year());
}
Please note that there are lots of ways to do this in a prettier fashion, and with less data copies.

Related

Sorting vector objects with accessor

This is part of a C++ program based on the Alternative Vote electoral method, using VS2015. I have a class for Party
#pragma once
#ifndef _PARTY_H
#define _PARTY_H
#include <string>
class Party {
public:
Party();
~Party();
Party(std::string n, int pos);
void reset();
void upTotal();
int getPosition();
std::string getName();
int getVotes();
private:
std::string name;
int votes;
int position;
};
#endif
and
#include <iostream>
#include "Party.h"
using namespace std;
Party::Party() {}
Party::~Party() {}
Party::Party(string n, int p) {
name = n;
position = p;
}
void Party::reset() {
votes = 0;
}
void Party::upTotal() {
votes += 1;
}
int Party::getPosition() {
return position;
}
string Party::getName() {
return name;
};
int Party::getVotes() {
return votes;
}
I tried to sort on votes received using (calculated from ballot papers elsewhere in the program
void sortParties() {
sort(parties.begin(), parties.end(), [](const auto& a, const auto& b)
{
return a.getVotes() < b.getVotes();
});
}
which returned illegal operand errors. Moving the variables from private to public and writing the following did work
void sortParties() {
sort(parties.begin(), parties.end(), [](const auto& a, const auto& b)
{
return a.votes < b.votes;
});
}
which gets it working, but I want to write it with proper encapsulation using private variables and an accessor for votes. Do I need to overload somehow, or convert type?
You have the following functions defined:
int getPosition();
std::string getName();
int getVotes();
They should probably all be const; ie
int getPosition() const;
std::string getName() const;
int getVotes() const;
This will allow you to call the functions from your const object at
sort(parties.begin(), parties.end(), [](const auto& a, const auto& b)

C++, Constructors: Out-of-line definition of 'class' does not match any declaration in 'class'

So I was trying to program a target heart rate calculator in C++ and when I tried to build it, this error was returned. Just to let you know, I am instructed to separate the implementation and interface.
Here's the interface
#include <iostream>
#include <string>
class HeartRates
{
public:
// constructor initialize HeartRates
HeartRates( std::string, std::string, int, int, int );
// Setting each variable
void setFirstName( std::string );
void setLastName( std::string );
void setdobMonth( int );
void setdobDay( int );
void setdobYear( int );
void setCurrentYear( int );
std::string getFirstName() const;
std::string getLastName() const;
int getdobMonth() const;
int getdobDay() const;
int getdobYear() const;
int getCYear() const;
int getAge() const;
int getMaximumHeartRate() const;
int getTargetHeartRate() const;
private:
std::string firstName;
std::string lastName;
int dobMonth;
int dobDay;
int dobYear;
int currentYear;
};
And here's the implementation
#include <iostream>
#include <string>
#include "HeartRates.h"
using namespace std;
// constructor that initializes all the stuff
This is the line that is giving me this error: Out-of-line definition of 'HeartRates' does not match any declaration in 'HeartRates'
HeartRates::HeartRates( string first, string last, int M, int D, int Y, int cY )
{
setFirstName( first );
setLastName( last );
setdobMonth( M );
setdobDay( D );
setdobYear( Y );
setCurrentYear( cY );
}
Continue on with the code
// set functions
void HeartRates::setFirstName( string first )
{
firstName = first; // store the first name in the object
}
void HeartRates::setLastName( string last )
{
lastName = last; // store the last name in the object
}
void HeartRates::setdobMonth( int M )
{
dobMonth = M; // store the month of birth in the object
}
void HeartRates::setdobDay( int D )
{
dobDay = D; // store the day of birth in the object
}
void HeartRates::setdobYear( int Y )
{
dobYear = Y; // store the year of birth in the object
}
void HeartRates::setCurrentYear( int cY )
{
currentYear = cY;
}
// get functions
string HeartRates::getFirstName() const
{
return firstName; // return user's first name
}
string HeartRates::getLastName() const
{
return lastName; // return user's last name
}
int HeartRates::getdobMonth() const
{
return dobMonth;
}
int HeartRates::getdobDay() const
{
return dobDay;
}
int HeartRates::getdobYear() const
{
return dobYear;
}
int HeartRates::getCYear() const
{
return currentYear;
}
// Functions
int HeartRates::getAge() const
{
int age;
age = currentYear-dobYear;
return age;
}
int HeartRates::getMaximumHeartRate() const
{
int maxHeartRate;
maxHeartRate = 220 - getAge();
return maxHeartRate;
}
int HeartRates::getTargetHeartRate() const
{
int targetHeartRate;
targetHeartRate = getMaximumHeartRate() * 0.85;
return targetHeartRate;
}
Sorry for the formatting and copy and pasting everything. Newbie here, I just don't know which part of the code went wrong.
HeartRates( std::string, std::string, int, int, int );
2 strings and 3 int.
HeartRates::HeartRates( string first, string last, int M, int D, int Y, int cY )
2 strings and 4 int.
I had a similar issue today and my fix was slightly different, so I'll throw this here in case it ever helps anyone in the future. I had forward declared a class OUTSIDE of the appropriate namespace in the header, so my error looked something like this:
1. Type of 1st parameter of member declaration does not match definition
'const std::shared_ptr<MyClass> &' (aka 'const shared_ptr<MyClass> &') vs
'const std::shared_ptr<MyClass> &' (aka 'const shared_ptr<myNamespace::MyClass> &'))
The solution for me was to forward declare that class inside the namespace, rather than outside it.
Bad:
class MyClass;
namespace myNamespace {
}
Good:
namespace myNamespace {
class MyClass;
}

header's constroctor ending before it should

For some reason my, makefile will not compile. The error it is talking about is in my header.
Alignment.hh:34:22 error: expected ')' before '&' token
The calls are supposed to be using the references, which I have in when I call this function.
This is my Alignment.hh file
#ifndef encod
#define encod
class Encoded
{ private:
Direct &origin;
char *subinsertion;
int subinsertlen;
struct Edit *operation;
int editnum;
string dname;
int dlength;
int gaplen;
public:
Encoded(Alignment &obj);
~Encoded();
int getEditNum() const;
struct Edit* getOperation() const;
int getSubInsertLen() const;
char* getSubInsertion() const;;
int getDLength() const;
string getDName() const;
Direct& getOrigin() const;
string toString() const;
char* getDSeq() const;
int getNumDiff();
bool operator<=(Encoded &rightobj)const;
};
class Compressed : public Encoded {
private:
Encoded encode;
public:
Compressed(Alignment &obj);
bool operator <=(Encoded &rightobj) const;
};
#endif
Try to compile this
#ifndef encod
#define encod
class Direct;
class Alignment;
class Encoded
{ private:
Direct &origin;
char *subinsertion;
int subinsertlen;
struct Edit *operation;
int editnum;
string dname;
int dlength;
int gaplen;
public:
Encoded(Alignment &obj);
~Encoded();
int getEditNum() const;
struct Edit* getOperation() const;
int getSubInsertLen() const;
char* getSubInsertion() const;;
int getDLength() const;
string getDName() const;
Direct& getOrigin() const;
string toString() const;
char* getDSeq() const;
int getNumDiff();
bool operator<=(Encoded &rightobj)const;
};
class Compressed : public Encoded {
private:
Encoded encode;
public:
Compressed(Alignment &obj);
bool operator <=(Encoded &rightobj) const;
};
#endif

Sort vector of object pointers

I'm creating a c++ program of a race.
I have the race class. Each race has a name, a distance and vector of results pointers(its a result for each participant).
The result class has a pointer to the participant and a time.
The class time has hours, minutes and seconds.
I want to sort the vector of results from the fastest time to the slowest, so to compare results I created the function bool operator <(Result& res2) const in the class result.
All the functions in the .h file are implemented, I'm just not showing them all.
I'm almost certain that the function sortResults is not right but the function operator< is giving me errors that I don't know how to solve. It gives me this error in all the if statements: Multiple markers at this line
- passing 'const Time' as 'this' argument of 'unsigned int Time::getHours()' discards qualifiers [-
fpermissive]
- Line breakpoint: race.cpp [line: 217]
- Invalid arguments ' Candidates are: unsigned int getHours() '
Can you tell me what I'm doing wrong?
.h file:
class Time
{
unsigned int hours;
unsigned int minutes;
unsigned int seconds;
public:
Time(unsigned int h, unsigned int m, unsigned int s, unsigned int ms);
Time();
unsigned int gethours();
unsigned int getMinuts();
unsigned int getSeconds();
string show();
};
class Participant {
string name;
unsigned int age;
string country;
public:
Participant(string n, unsigned int a, string c);
string getName();
string getCountry();
int getAge();
string show() const;
};
class Result {
Participant *part;
Time time;
public:
Result(Participant *p, Time t);
Participant *getParticipant() const;
Time getTime();
string show();
bool operator <(Result& res2) const;
};
class Race {
string name;
float distance;
vector<Result *> results;
public:
Race(string nm, float dist);
string getName();
void setName(string nm);
float getDistance();
vector<Result *> sortResults();
void addResult(Result *r);
string showRaceResults();
string show();
};
.cpp file:
bool Result::operator <(Result& res2) const {
if (time.gethours() < res2.getTime().gethours())
return true;
else {
if (time.gethours() > res2.getTime().gethours())
return false;
else {
if (time.getMinutes() < res2.getTime().getMinutes())
return true;
else {
if (time.getMinutes() > res2.getTime().getMinutes())
return false;
else {
if (time.getSeconds() < res2.getTime().getSeconds())
return true;
else {
return false;
}
}
}
}
}
}
vector<Result *> Race::sortResults() {
sort (results.begin(), results.end(), operator <);
return results;
}
You should declare and define Time::gethours() as constant member function.
class Time {
// ...
unsigned int gethours() const; // note the "const"
};
unsigned int Time::gethours() const { /* ... */ } // note the "const"
To sort vector<Result*>, you need to
Change Result::operator<() to take const Result& rather than Result& as parameter
Define a comparison function for Result* which looks like static bool cmpResultPtr(const Result* lhs, const Result* rhs) { return *lhs < *rhs; }
Call sort(results.begin(), results.end(), cmpResultPtr);
The function cmpResultPtr() could be defined in the .cpp file, before the definition of Race::sortResults().
You declare operator< to be const but Time::getHours, which it calls, doesn't have the same declaration. To the compiler, this means getHours could change the value of the time member which violates the constness of operator<.

How to get struct member with a string using Macros C++

Consider the following example:
struct MyStruct {
int a;
int b;
};
I can use macros to set a member from an instance of the struct by doing this:
#define setVar(x,y) instance.x = y
then in any function I can say:
setVar(a, 4)
How can I send in a as a string to the macro? Is that also possible?
setVar("a", 4)
EDIT: There are a bunch of predefined structs with members that are all of type double. I only know what struct I am using by an XML config file that is passed in. After parsing, I have a bunch of strings that are a list of all the data members and values that need to be set. I need to use this list to set values for each of the members in the struct.
It is only possible if you define the struct itself using some macro, for example:
#define MY_STRUCT_STRUCTURE FIELD(a) FIELD(b) FIELD(d) FIELD(e) FIELD(f)
struct MyStruct {
# define FIELD(name) int name;
MY_STRUCT_STRUCTURE
# undef FIELD
bool setVar(char* fieldname, int val)
{
# define FIELD(name) if(strcmp(#name,fieldname)==0){name=val; return true;};
MY_STRUCT_STRUCTURE
# undef FIELD
return false; // name not found
}
};
int main()
{
MyStruct s;
s.setVar("a",1);
s.setVar("b",2);
s.setVar("f",100);
}
I have coded some quick and dirty code, but could give you some ideas, hope that helps. The main trick here is too use unions.
struct MyStruct
{
int a;
double b;
MyStruct()
: a(0), b(0) {}
};
MyStruct instance;
union value
{
long value_a;
double value_d;
} myvalue;
void blah_a(value v)
{
instance.a = v.value_a;
}
void blah_b(value v)
{
instance.b = v.value_d;
}
struct
{
(void)(*fn)(value);
const char* key;
}
lookup_table[] =
{
{ &blah_a, "a" },
{ &blah_b, "b" }
};
void setVar(const char* c, value v)
{
for (int i = 0; lookup_table[i].fn; i++)
if (c == lookup_table[i].key)
(*(lookup_table[i].fn))(v);
}
int main(int argc, char* argv[])
{
value v;
v.value_a = 6;
setVar("a", v);
return 0;
}
Might not be what you are looking for but an alternative solution to macros etc.. would just be some encapsulation and OO design. You can change the Field class to a template later and you will be able to represent anything basically.
You can create a class
class Field
{
public:
Field(const std::string& name, const std::string& type);
virtual ~Field(void);
std::string toString() const;
std::string getName() const;
int getValue() const { return value };
private:
std::string name;
std::string type;
int value;
};
And then a structure class
#pragma once
#include <boost/ptr_container/ptr_deque.hpp>
#include <string>
class Field;
class MyStructure
{
public:
typedef boost::ptr_deque<Field> FieldList;
typedef FieldList::iterator FieldListIter;
typedef FieldList::auto_type AutoField;
MyStructure(void);
MyStructure(const std::string& name);
virtual ~MyStructure(void);
void setName(const std::string& name);
std::string getName() const;
void addField( std::auto_ptr<Field> field );
std::string getFieldValue( const std::string& name ) const;
MyStructure::AutoField removeField( const std::string& name );
std::string toString(void) const;
private:
std::string struct_name;
FieldList fields;
};
And then to use it:
auto_ptr<MySructure> struct_a(new MySructure("StructName1",0) );
struct_a->addField( auto_ptr<Field> ( new Field( "Field1", 1 ) ) );
struct_a->addField( auto_ptr<Field> ( new Field( var_str1, 2) ) );
struct_a->addField( auto_ptr<Field> ( new Field( getName(), getVal() ) ) );