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)
Related
I am trying to pass a custom c++ object reference to a simple chai script so that the chai script can eventually read/access/call public variables & methods.
I'm not certain if this is even possible, nor if once it is passed inside of the chai script function if it will have access to the classes values without having the class previously defined within chai... Any insight would be very helpful, as I can't find a specific section in the documentation relating to this.
Here is a very basic implementation.
ChaiScript.h
#pragma once
#include "ChaiScript\include\chaiscript\chaiscript.hpp"
class ChaiScript
{
public:
explicit ChaiScript(
const std::string& script_name);
~ChaiScript();
chaiscript::ChaiScript chai;
private:
};
ChaiScript.cpp
#include "ChaiScript.h"
ChaiScript::ChaiScript(
const std::string& script_name)
{
chai.add(chaiscript::vector_conversion<std::vector<int>>());
chai.eval_file(script_name);
}
ChaiScript::~ChaiScript()
{
}
SampleClass.h
#pragma once
#include <string>
class SampleClass
{
public:
SampleClass(
const int id,
const int x,
const int y,
const std::string& name);
const int m_id;
int m_x;
int m_y;
std::string m_name;
private:
// Disable copying as we don't want to make a copy each time we pass the class to chai...
SampleClass();
SampleClass(const SampleClass& rhs);
SampleClass& operator=(const SampleClass& rhs);
};
SampleClass.cpp
#include "SampleClass.h"
SampleClass::SampleClass(
const int id,
const int x,
const int y,
const std::string& name) :
m_id(id),
m_x(x),
m_y(y),
m_name(name)
{
}
main.cpp
#include "ChaiScript.h"
#include "SampleClass.h"
int main()
{
SampleClass* sample_class = new SampleClass(0, 1, 2, "Test");
ChaiScript* script = new ChaiScript("Scripts\\SampleScript.chai");
// This line is where I start to need help as it does not compile.
script->chai.eval<std::function<void(&SampleClass)>>("ReceiveSampleClass")(&sample_class);
system("pause");
return 0;
}
SampleScript.chai
def ReceiveSampleClass(SampleClass sample)
{
var result = sample.m_x + sample.m_y;
print("2+2=" + to_string(result));
}
After a bit more searching, I found out how to do this!
I've changed ChaiScript.cpp to the following:
#include "ChaiScript.h"
#include "SampleClass.h"
ChaiScript::ChaiScript(
const std::string& script_name)
{
chai.add(chaiscript::vector_conversion<std::vector<int>>());
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
chaiscript::utility::add_class<SampleClass>(*m,
"SampleClass",
{
chaiscript::constructor<SampleClass(const int id, const int x, const int y, const std::string & name)>()
},
{
{chaiscript::fun(&SampleClass::m_x), "X"}
});
chai.add(m);
chai.eval_file(script_name);
}
ChaiScript::~ChaiScript()
{
}
My SampleScript.chai also changed to:
def ReceiveSampleClass(SampleClass sample)
{
var result = sample.X;
sample.X += 2;
var result2 = sample.X;
print("1) " + to_string(result));
print("2) " + to_string(result2));
}
The process I was missing was adding the class to a module and adding that to chai script.
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
chaiscript::utility::add_class<SampleClass>(*m,
"SampleClass",
{
chaiscript::constructor<SampleClass(const int id, const int x, const int y, const std::string & name)>()
},
{
{chaiscript::fun(&SampleClass::m_x), "X"}
});
chai.add(m);
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.
I have something like this:
using namespace std;
class QuadraticPrimeSolution
{
private:
int a;
int b;
int numberOfPrimes;
bool isPrime(int n, set<int> &primeHash);
public:
QuadraticPrimeSolution(int a, int b):a(a),b(b),numberOfPrimes(0){};
void calculateNumberOfPrimes(set<int> &primeHash);
int getNumberOfPrimes(){return numberOfPrimes;}
};
class QuadraticPrimeSolver
{
private:
struct classcomp {
bool operator() (QuadraticPrimeSolution& lhs, QuadraticPrimeSolution& rhs)
{
return lhs.getNumberOfPrimes()>rhs.getNumberOfPrimes();
}
};
set<QuadraticPrimeSolution, classcomp> solutions;
set<int> primeHash;
QuadraticPrimeSolution getMaxSolution();
int a;
int b;
public:
QuadraticPrimeSolver(int a, int b):a(a), b(b){};
void solve();
};
bool QuadraticPrimeSolution::isPrime(int n, set<int> &primeHash)
{
if(primeHash.empty())
{
primeHash.insert(n);
return true;
}
for(auto it= primeHash.begin(); it!= primeHash.end(); it++)
{
if(n%(*it)==0)
{
return false;
}
}
primeHash.insert(n);
return true;
}
void QuadraticPrimeSolver::solve()
{
for(int i=(-1)*a; i<=a; i++)
{
for(int j=(-1)*b; j<=b; j++)
{
QuadraticPrimeSolution aSolution = new aSolution(i,j);
aSolution.calculateNumberOfPrimes(primeHash);
solutions.insert(aSolution);
}
}
}
int main()
{
QuadraticPrimeSolver QPS(0,40);
QPS.solve();
}
Basically what I am trying to do is compute and store each QuadraticPrimeSolution into a hash table in QuadraticPrimeSolver which I can then access later.
My question is, is my comparator implementation correct? Right now compiler is complaining about my comparator, and the following line for inserting into a set.
solutions.insert(aSolution);
Please help!
class building
{
public:
int getPosition() const {return position;};
private:
int height;
int position;
};
class ManyBuildings
{
public:
void populateBuildings(std::vector<std::string> buildings);
private:
class comparePosition {
public:
bool operator () (const building &lhs, const building &rhs) {
return lhs.getPosition() > rhs.getPosition();
}
};
std::set<building, comparePosition> buildings;
};
use set instead of unordered_set
template parameter for set should be a type, not a function
I'm trying to access one of my pointers within my class, however I can't seem to even get VS to acknowledge the pointer is there.
private:
ForwardTo* forward;
and here's how I grab it from the class
ForwardTo& Persons::getForwardTo() const
{
return *forward;
}
The ForwardTo type is an inherited class that typically reads:
class ForwardToTwo : public ForwardTo
{
public:
ForwardToTwo(unsigned int strategy);
virtual std::vector<std::string> forwardMessage(Persons& person, Message& message);
unsigned int getStrategy() const { return strategy;};
private:
unsigned int strategy;
};
and finally, here's how I'm trying to access the pointer
listOfPersons.at(i).getForwardTo()->forwardMessage(listOfPersons.at(i), tempMessage);
This style of access worked previously for my OTHER pointer in my class that acts exactly this same as this one.
While typing the line to access the pointer out in VS, intelliSense picks up all the functions up to getForwardTo(), and after that, the dot operator/arrow operator don't bring up any access to functions.
Thanks again for all help.
(edit, I'm aware the function fordwardMessage() function will return a vector, I was just typing in the VS until intelliSense failed to detect the accessible functions)
(edit 2, I've tried both the . operator and the -> operator, yet neither allow intelliSense to detect any functions.)
(edit 3, additional code:
Here is my Persons Class Header:
#ifndef PERSONS_HPP
#define PERSONS_HPP
#include <string>
#include <vector>
#include <list>
#include <map>
#include "Message.hpp"
#include "TypeOne.hpp"
#include "TypeTwo.hpp"
#include "TypeThree.hpp"
#include "TypeFour.hpp"
#include "TypeFive.hpp"
class ForwardTo;
class ForwardToOne;
class ForwardToTwo;
class ForwardToThree;
class Persons
{
public:
Persons();
~Persons();
void setEmailAddress(std::string email);
std::string getEmailAddress() const;
const std::vector<std::string>& getContactList() const;
void addMessageSeen(Message message);
void addMessageContent(MessageContent mc);
void addInboxMessage(Message message);
void addContact(std::string contact);
void viewContact(const std::vector<std::string>& contacts);
void bumpContact();
void setMessageTypeOne();
void setMessageTypeTwo(unsigned int type);
void setMessageTypeThree(unsigned int quality);
void setMessageTypeFour(unsigned int type, unsigned int quality);
void setMessageTypeFive();
void setForwardTypeOne(unsigned int strategy);
void setForwardTypeTwo(unsigned int strategy);
void setForwardTypeThree(unsigned int strategy);
void printPersonsObj();
std::list<Message> getInbox() const;
MessageType& getForwardWhen() const;
ForwardTo& getForwardTo() const;
private:
std::map<MessageContent, unsigned int> messageList;
std::list<Message> inbox;
std::vector<std::string> contactList;
std::string emailAddress;
ForwardTo* forward;
MessageType* forwardWhen;
};
And here is my Persons.cpp file is:
#include "Persons.hpp"
#include "ForwardToOne.hpp"
#include "ForwardToTwo.hpp"
#include "ForwardToThree.hpp"
#include <iostream>
Persons::Persons()
:emailAddress(""), contactList(), inbox(), messageList()
{
}
Persons::~Persons()
{
//delete forwardWhen;
//delete forwardTo;
}
void Persons::addMessageContent(MessageContent mc)
{
//messageSeen.insert(mc);
}
void Persons::setEmailAddress(std::string email)
{
emailAddress = email;
}
std::string Persons::getEmailAddress() const
{
return emailAddress;
}
void Persons::addContact(std::string contact)
{
contactList.push_back(contact);
}
void Persons::addInboxMessage(Message message)
{
inbox.push_back(message);
}
void Persons::viewContact(const std::vector<std::string>& contacts)
{
for(auto i = contacts.begin(); i != contacts.end(); i ++)
{
std::cout << *i << std::endl;;
}
}
void Persons::setMessageTypeOne()
{
MessageType* forwardWhen = new TypeOne();
}
void Persons::setMessageTypeTwo(unsigned int type)
{
MessageType* forwardWhen = new TypeTwo(type);
}
void Persons::setMessageTypeThree(unsigned int quality)
{
MessageType* forwardWhen = new TypeThree(quality);
}
void Persons::setMessageTypeFour(unsigned int type, unsigned int quality)
{
MessageType* forwardWhen = new TypeFour(type, quality);
}
void Persons::setMessageTypeFive()
{
MessageType* forwardWhen = new TypeFive();
}
void Persons::setForwardTypeOne(unsigned int strategy)
{
ForwardTo* forward = new ForwardToOne(strategy);
}
void Persons::setForwardTypeTwo(unsigned int strategy)
{
ForwardTo* forward = new ForwardToTwo(strategy);
}
void Persons::setForwardTypeThree(unsigned int strategy)
{
ForwardTo* forward = new ForwardToThree(strategy);
}
const std::vector<std::string>& Persons::getContactList() const
{
return contactList;
}
void Persons::bumpContact()
{
std::vector<std::string> tempList = getContactList();
std::string tempContact = tempList.at(0);
for(unsigned int i = 0; i <= tempList.size(); i ++)
{
if(i == tempList.size())
tempList.at(--i) = tempContact;
else
tempList.at(--i) = tempList.at(i);
}
}
void Persons::addMessageSeen(Message message)
{
messageList[*message.getMessageContent()] = message.getMessageContent()->getUniqueID();
}
void Persons::printPersonsObj()
{
std::cout << "PERSONS OBJECT!" << std::endl;
std::cout << "E-mail Address: " << emailAddress << std::endl;
std::cout << std::endl;
}
std::list<Message> Persons::getInbox() const
{
return inbox;
}
MessageType& Persons::getForwardWhen() const
{
return *forwardWhen;
}
ForwardTo& Persons::getForwardTo() const
{
return *forward;
}
Incomplete type normally means that at the point at which you are trying to use getForwardTo, you have not fully declared the ForwardTo class. Indeed in your persons.hop there is only a forward declaration.
Make sure you have included the header that fully declares ForwardTo in the file containing the call site.
getForwardTo() returns a T&, just use the . to access forwardMessage()
I have the following code
#include<iostream>
using namespace std;
class operate
{
int x;
int y;
public:
operate(int _x, int _y):x(_x), y(_y)
{}
void add(const char* ch)
{
cout<<ch<<" "<<x+y;
}
void subtract(const char* ch)
{
cout<<ch<<" "<<x-y;
}
void multiply(const char* ch)
{
cout<<ch<<" "<<x*y;
}
};
int main()
{
void (operate::*fptr[3])(const char*);
operate obj(2,3);
fptr[0] = &(operate.add); //problem
fptr[1] = &(operate.multiply); //problem
fptr[2] = &(operate.subtract); //problem
(obj.*fptr[0])("adding");
(obj.*fptr[1])("multiplying");
(obj.*fptr[2])("subtracting");
}
It seems I am not assigning the member functions to function pointer array properly. How can I solve this. I'm using VS2010
The dot (member-of) operator is used for accessing members of an object. For classes and namespaces, you have to use the :: operator. Also, don't parenthesize, since & has lower precedence than :: and it's more readable like
fptr[0] = &operate::add;
This should do the job
void testFP()
{
typedef void (operate::*memFP)(const char*);
memFP fptr[3];
fptr[0] = &operate::add;
fptr[1] = &operate::multiply;
fptr[2] = &operate::subtract;
operate op(42, 42);
(op.*(fptr[0]))("adding");
}