Troubles with std::set.insert c++ - c++

I have a set of a custom class and when I'm trying to insert an object of that class, the terminal gives me an error:
#ifndef EMPLOYEE_HH
#define EMPLOYEE_HH
#include <string>
#include <iostream>
#include <set>
#include <iterator>
using namespace std ;
class Employee {
public:
// Constructor
Employee(const char* name, double salary) : _name(name), _salary(salary) {}
// Accessors
const char* name() const { return _name.c_str() ; }
double salary() const { return _salary ; }
// Print functions
void businessCard(ostream& os = cout) const {
os << " +------------------+ " << endl
<< " | ACME Corporation | " << endl
<< " +------------------+ " << endl
<< " " << name() << endl ;
}
private:
string _name ;
double _salary ;
} ;
class Manager : public Employee{
public:
Manager(const char* name, double salary) : Employee(name, salary) {};
void addSubordinate(Employee& empl){
_subs.insert(empl);
}
const set<Employee*>& listOfSubordinates() const{
return _subs;
}
void businessCard() const{
Employee::businessCard();
set <Employee*>::iterator it=_subs.begin();
cout <<"Managed employees: " <<endl;
while(it!=_subs.end()){
cout <<*it++ <<endl;
}
}
private:
set <Employee*> _subs;
};
#endif
The addSubordinate() routine:
void addSubordinate(Employee& empl){
_subs.insert(empl);
}
returns this error:
no instance of overloaded function "std::set<_Key, _Compare, _Alloc>::insert [with _Key=Employee *, _Compare=std::less<Employee *>, _Alloc=std::allocator<Employee *>]" matches the argument list
I have tried to overload the operator < as other people suggested in response to similar questions, but that doesn't seem to solve the issue.

Your set accepts a pointer to an Employee, but you are trying to insert the object itself.
What you can do is
void addSubordinate(Employee& empl){
_subs.insert(&empl); // This will store the address to the object
}
or accept a pointer itself
void addSubordinate(Employee* empl){
_subs.insert(empl);
}

You need to define the < operator in the Employee class. The items in a set are always sorted and since you don't have a comparator it won't let you insert an instance of that class.
Try something like this:
bool operator<(const Employee& emp){
return salary() < emp.salary();
}

Related

Some guidance with C++ and creating objects using composition

Basically my issue is with compositions. I understand the principle, but I'm struggling with the execution in one of the tests.
From the code of Computer and Monitor below, I have to create a final class Complect which will have its own name , the name of the computer, the name of the monitor, and a price which will be made up from the price() functions.
Computer.h
#ifndef COMPUTER_H
#define COMPUTER_H
#include <string>
class Computer{
public:
Computer(std::string name, int ram, double price);
std::string name() const;
int ram() const;
double price() const;
void printComputer() const;
void setComputer(std::string name, int ram, double price);
private:
std::string its_name;
int ram_gb;
double cost_price;
};
#endif // COMPUTER_H
Computer.cpp
#include "Computer.h"
#include <iostream>
Computer::Computer(std::string name, int ram, double price)
: its_name(name), ram_gb(ram), cost_price(price){
}
std::string Computer::name() const {
return its_name;
}
int Computer::ram() const {
return ram_gb;
}
double Computer::price() const {
return cost_price;
}
void Computer::printComputer() const{
std::cout << "Computer name = " <<name() <<"\n"
<< "Computer RAM = " <<ram() <<" GB\n"
<< "Computer Price = " << price() <<" EUR \n";
}
Monitor.h
#ifndef MONITOR_H
#define MONITOR_H
#include <string>
class Monitor{
public:
Monitor(std::string name, std::string type, double price);
std::string name() const;
std::string type() const;
double price() const;
//print computer
void printMonitor() const;
//set computer
void setMonitor(std::string name, std::string type, double price);
private:
std::string its_name;
std::string type_set;
double cost_price;
};
#endif // MONITOR_H
Monitor.cpp
#include "Monitor.h"
#include <iostream>
Monitor::Monitor(std::string name, std::string type, double price) : its_name(name), type_set(type), cost_price(price){
}
std::string Monitor::name() const {
return its_name;
}
std::string Monitor::type() const{
return type_set;
}
double Monitor::price() const {
return cost_price;
}
void Monitor::printMonitor() const{
std::cout << "Monitor name = " <<name() <<"\n"
<< "Monitor type = " <<type() <<"\n"
<< "Monitor price = " << price() <<" EUR \n";
}
Here is the class that I have made:
Complect.h
#ifndef COMPLECT_H
#define COMPLECT_H
#include <string>
class Complect{
public:
Complect(std::string name, std::string computername, std::string monitorname, double price);
std::string name() const;
std::string computername() const;
std::string monitorname() const;
double price() const;
void printComplect();
void setComplect(std::string name, std::string computername, std::string monitorname, double price);
private:
std::string complect_name;
std::string computername_final;
std::string monitorname_final;
double cost_price;
};
#endif // COMPLECT_H
Complect.cpp
#include "Complect.h"
#include "Monitor.h"
#include "Computer.h"
#include <iostream>
Complect::Complect(std::string name, std::string computername, std::string monitorname, double price) :
complect_name(name), computername_final(computername), monitorname_final(monitorname), cost_price(price){
}
std::string Complect::name() const{
return complect_name;
}
std::string Complect::computername() const{
return computername_final;
}
std::string Complect::monitorname() const{
return monitorname_final;
}
double Complect::price() const{
return cost_price;
}
void Complect::printComplect(){
std::cout << "Complect name = " << name() <<"\n"
<< "Computer name = " <<computername() <<"\n"
<<"Monitor name = " <<monitorname() <<"\n"
<<"Complect price = " <<price() <<" EUR \n";
}
Here is how I use the classes in Main.cpp
#include <iostream>
#include "Computer.h"
#include "Monitor.h"
#include "Complect.h"
int main(){
Computer asus("Asus One", 8, 545.95) ;
asus.printComputer() ;
std::cout << "\n";
Monitor iiyama("Iiyama Blackhawk 27inch", "LED", 299.99);
iiyama.printMonitor();
std::cout <<"\n";
Complect numberOne ("Number one complect", asus.name(), iiyama.name(), iiyama.price() + asus.price());
numberOne.printComplect();
std::cout <<"\n";
system ("pause");
return 0;
}
The end result is what it should be, so this code works.
But the issue with this is that it's incorrectly structured.
In the main.cpp file you will see that the Complect object is being created. But I currently provide all of the informations of that object at construction in main.cpp file.
Sorry the codes a bit messy, but im trying to wrap my head around this and struggling at the moment... How to make the class in complect.cpp file provide itself all its information ?
Currently you do not use composition but copy the attributes from the two other classes and you do a lot of work in the call of the constructor from main
A first little change from your code is to get instances of Computer and Monitor in parameter in the constructor:
Complect(std::string name, const Computer &, const Monitor &);
of course the final price is also computed inside that constructor, in main you just create a Complect with its name and its parts :
Complect numberOne ("Number one complect", asus, iiyama);
Now main fortunately does not have to know how the price is computed, else imagine if the formula change and you have to update all the calls of the constructor :-(. The way the price is computed is only the responsibility of Complect.
Complect numberOne ("Number one complect", asus, iiyama);
More than the constructor setComplect must be updated to receive the price of the monitor and computer separated for the same reason.
void setComplect(std::string name, std::string computername, std::string monitorname, double computerprice, double monitorprice);
or probably better to replace it by the methods
void setname(std::string name);
void setcomputer(std::string computername, double computerprice);
void setmonitor(std::string monitorname, double monitorprice);
But to duplicate all the attributes of Computer and Monitor in Complect is not practical, and you do not have composition to the instances. A first possibility is to save a copy of them :
class Complect{
...
private:
Computer computer;
Monitor monitor;
// does not need attribute "double cost_price;"
...
};
Complect::Complect(std::string name, const Computer & c, const Monitor & m)
: complect_name(name), computer(c), monitor(m) {
}
std::string Complect::computername() const{
return computer.name();
}
std::string Complect::monitorname() const{
return monitor.name();
}
double Complect::price() const{
return computer.price() + monitor.price();
}
void Complect::printComplect(){
std::cout << "Complect name = " << name() <<"\n"
<< "Computer name = " << computer.name() <<"\n"
<<"Monitor name = " << monitor.name() <<"\n"
<<"Complect price = " << price() <<" EUR \n";
}
The advantage of that solution is you are not impacted if the initial instances of Monitor and Computer disappear. The disadvantage is for instance the price is not updated if the price of one of the cloned part changes except by calling setXXX
An other way is to not clone the Monitor and Conputer, but you cannot have just that :
class Complect{
...
private:
Computer & computer;
Monitor & monitor;
// does not need attribute "double cost_price;"
...
};
Complect::Complect(std::string name, const Computer & c, const Monitor & m)
: complect_name(name), computer(c), monitor(m) {
}
because that supposes the instances of Monitor and Computer still exist while the corresponding instance of Complect exists
Fortunately C++ offers interesting features to manage that

copy constructor syntax & display the values of constructor

I am writing a program where I need to use copy constructor. Since I am novice in using copy constructor I do not know whether my declaration and using of copy constructor is valid or not?
Also here I am facing problem with the display function, the error is ::
error: prototype for 'int Student::display_student()' does not match any in class 'Student'. What is this error?
#include <string>
#include <iostream>
using namespace std;
class Student
{
private:
int rollno;
string name;
public:
Student();
Student(int x, string str);
Student(Student &s);
void display_student();
};
Student::Student()
{
rollno = 0 ;
name = "" ;
}
Student::Student(int x, string str)
{
rollno=x ;
name=str ;
}
Student::Student(Student &s)
{
rollno = s.rollno ;
name = s.name;
}
Student::display_student()
{
cout << "Student Name ::" << name << endl << "Student Roll No. ::" << rollno << endl;
}
int main()
{
Student A;
Student B(09,"Jhonny");
Student C(B);
A.display_student();
B.display_student();
C.display_student();
return 0;
}
You didn't specify the return value in the definition of Student::display_student(). Try:
void Student::display_student()
{
cout << "Student Name ::" << name << endl << "Student Roll No. ::" << rollno << endl;
}
Compiler assumes int Student::display_student() by default. The class declaration contains the prototype for void display_student() but you provided only the definition for function int display_student().
Copy constructor signature uses generally const reference. In your case, you may use the default implementation:
Student(const Student&) = default;
You may also add copy assignment:
Student& operator=(const Student&) = default;

C++ questions on Inheritance, privacy, and objects in a shipping program with multiple classes and headers

My program is supposed to print a "to" and "from" address sourced from the EndPoint toString method but I can't quite figure out how to implement it. Here is my code. How do I get the toString method in the Package::Package constructor to print the contents of the EndPoint's toString method?
// ShippingProgram.cpp :
//
#include "stdafx.h"
#include <iomanip>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include "Package.h" // Package class definition
using namespace std;
// constructor
EndPoint::EndPoint(const string& nameInfo, const string& addressInfo, const string& cityInfo, const string& stateInfo, int zipInfo) {
name = nameInfo;
address = addressInfo;
city = cityInfo;
state = stateInfo;
zip = zipInfo;
}
string EndPoint::toString() const {
ostringstream output;
output << fixed << setprecision(2); // two digits of precision
output << name << "\n" << address << "\n" <<
city << ", " << state << " " << zip;
return output.str();
}
Package::Package(EndPoint senderInfo, EndPoint receiverInfo, double weightInfo, double costPerOzInfo) {
weight = weightInfo; // should validate
costPerOz = costPerOzInfo;
}
void Package::calculateCost(double)
{
}
double Package::calculateCost() const {
return weight * costPerOz;
}
string Package::toString() const {
ostringstream output;
output << fixed << setprecision(2); // two digits of precision
output << "\nFrom:\n" << senderInfo.toString() << "\n\nTo:\n" << receiver <<
"\n\nWeight: " << weight << endl <<
"\nShipping cost:\n" << calculateCost();
return output.str();
}
Main Method:
#include <iostream>
#include <iomanip>
#include "stdafx.h"
//#include "TwoDayPackage.h"
//#include "OvernightPackage.h"
#include "Package.h"
using namespace std;
int main()
{
// Three address records.
EndPoint homer{ "Homer Simpson", "742 Evergreen Terrace", "Springfield",
"FL", 32401 };
EndPoint donald{ "Donald Duck", "1313 Webfoot Walk", "Duckburg",
"CA", 95501};
EndPoint kermit{ "Kermit Frog", "On the Swamp", "Leland", "MS", 38756 };
// This calls the base class constructor (regular fee).
Package regular{ homer, donald, 25.0, 0.20 };
// Defines output precision for floating point numbers (iomanip).
// cout << fixed << setprecision(2);
// Prints package parameters.
cout << "Regular package processed." << endl;
cout << regular.toString();
cout << "Shipping Cost: $" << regular.calculateCost() << endl << endl;
cout << homer.toString();
// First derived class (two-day fee added).
/* TwoDayPackage twoday{ donald, kermit, 17.5, 0.20, 2.0 };
cout << "Two-day package processed." << endl;
cout << twoday.toString();
cout << "Shipping Cost: $" << twoday.calculateCost() << endl << endl;
// Second derived class (overnight fee added).
OvernightPackage overnight{ kermit, homer, 14.2, 0.20, 0.50 };
cout << "Overnight package processed." << endl;
cout << overnight.toString();
cout << "Shipping Cost: $" << overnight.calculateCost() << endl << endl;
*/
}
This project requires that I create a shipping program with inheritance. It must include a "EndPoint" class that is private and contains the sender and receiver info and a "Package" class that compiles everything and puts it to string.
My Errors are with how in the world I get my Package constructor to be able to contain the information from my EndPoint class. Since the main method is formatted where the Package class must be (EndPoint, EndPoint, Weight, Cost) but it doesn't compile like that. I guess I just don't understand how to send the EndPoint info to the Package objects.
Here are my errors:
No instance of constructor "Package::Package" matches the argument list argument types are: (EndPoint, EndPoint, double, double)
Error C2440 'initializing': cannot convert from 'initializer list' to 'Package'
Error C3861 'setprecision': identifier not found
Package.h
#pragma once
#ifndef PACKAGE_H
#define PACKAGE_H
#include <string>
#include <iostream>
using namespace std;
class EndPoint {
public:
EndPoint(const std::string&, const std::string&, const std::string&, const std::string&, int = 0.0);
void setName(const std::string&);
std::string getName() const;
void setAddress(const std::string&);
std::string getAddresss() const;
void setCity(const std::string&);
std::string getCity() const;
void setState(const std::string&);
std::string getState() const;
void setZip(int);
int getZip() const;
string toString() const;
protected:
std::string name;
std::string address;
std::string city;
std::string state;
int zip;
};
class Package {
public:
string toString() const;
Package(const std::string&, const std::string&, double = 0.0, double = 0.0);
void setSender(const std::string&);
std::string getSender() const;
void setReceiver(const std::string&);
std::string getReceiver() const;
void setWeight(double);
double getWeight() const;
void setCostPerOz(double);
double getCostPerOz() const;
void calculateCost(double);
double calculateCost() const;
double calculateCost(double weight, double costPerOz)
{
double shipping;
shipping = weight * costPerOz;
cout << "The Base Cost = " << shipping << endl << endl;
return shipping;
}
protected:
std::string sender;
std::string receiver;
double weight; // gross weekly sales
double costPerOz; // commission percentage
};
#endif
Package.cpp
#include "stdafx.h"
#include <iomanip>
#include <stdexcept>
#include <sstream>
#include "Package.h" // Package class definition
using namespace std;
// constructor
EndPoint::EndPoint(const string& nameInfo, const string& addressInfo, const string& cityInfo, const string& stateInfo, int zipInfo) {
name = nameInfo;
address = addressInfo;
city = cityInfo;
state = stateInfo;
zip = zipInfo;
}
void EndPoint::setName(const string& nameInfo) {
name = nameInfo;
}
string EndPoint::getName() const { return name; }
void EndPoint::setAddress(const string& addressInfo) {
address = addressInfo;
}
string EndPoint::getAddresss() const { return address; }
void EndPoint::setCity(const string& cityInfo) {
city = cityInfo;
}
string EndPoint::getCity() const { return city; }
void EndPoint::setState(const string& stateInfo) {
state = stateInfo;
}
string EndPoint::getState() const { return state; }
void EndPoint::setZip(int zipInfo) {
zip = zipInfo;
}
int EndPoint::getZip() const {
return zip;
}
string EndPoint::toString() const {
ostringstream output;
output << fixed << setprecision(2); // two digits of precision
output << name << "\n" << address << "\n" <<
city << ", " << state << " " << zip;
return output.str();
}
string EndPoint::getState() const { return state; }
Package::Package(const string& senderInfo, const string& receiverInfo, double weightInfo, double costPerOzInfo) {
sender = senderInfo; // should validate
receiver = receiverInfo; // should validate
weight = weightInfo; // should validate
costPerOz = costPerOzInfo;
}
void Package::setSender(const string& senderInfo) {
sender = senderInfo; // should validate
}
string Package::getSender() const { return sender; }
void Package::setReceiver(const string& receiverInfo) {
receiver = receiverInfo; // should validate
}
string Package::getReceiver() const { return receiver; }
void Package::setWeight(double weightInfo) {
if (weightInfo < 0.0) {
throw invalid_argument("The package weight must be >= 0.0");
}
weight = weightInfo;
}
double Package::getWeight() const { return weight; }
void Package::setCostPerOz(double costPerOzInfo) {
costPerOz = costPerOzInfo;
}
double Package::getCostPerOz() const {
return costPerOz;
}
double Package::calculateCost() const {
return weight * costPerOz;
}
string Package::toString() const {
ostringstream output;
output << fixed << setprecision(2); // two digits of precision
output << "From:\n" << sender << "\n\nTo:\n" << receiver <<
"\n\nWeight: " << weight << endl <<
"\nShipping cost: " << calculateCost();
return output.str();
}
Main.cpp
#include <iostream>
#include <iomanip>
#include "stdafx.h"
//#include "TwoDayPackage.h"
//#include "OvernightPackage.h"
#include "Package.h"
using namespace std;
int main()
{
// Three address records.
EndPoint homer{ "Homer Simpson", "742 Evergreen Terrace", "Springfield",
"FL", 32401 };
EndPoint donald{ "Donald Duck", "1313 Webfoot Walk", "Duckburg",
"CA", 95501};
EndPoint kermit{ "Kermit Frog", "On the Swamp", "Leland", "MS", 38756 };
// This calls the base class constructor (regular fee).
Package regular{ homer, donald, 25.0, 0.20 };
// Defines output precision for floating point numbers (iomanip).
cout << fixed << setprecision(2);
// Prints package parameters.
cout << "Regular package processed." << endl;
cout << regular.toString();
cout << "Shipping Cost: $" << regular.calculateCost() << endl << endl;
// First derived class (two-day fee added).
/* TwoDayPackage twoday{ donald, kermit, 17.5, 0.20, 2.0 };
cout << "Two-day package processed." << endl;
cout << twoday.toString();
cout << "Shipping Cost: $" << twoday.calculateCost() << endl << endl;
// Second derived class (overnight fee added).
OvernightPackage overnight{ kermit, homer, 14.2, 0.20, 0.50 };
cout << "Overnight package processed." << endl;
cout << overnight.toString();
cout << "Shipping Cost: $" << overnight.calculateCost() << endl << endl;
*/
}
I have commented out blocks of code here as I am trying to just get the first part to work before diving into the rest.
Edit:
Thank you all for the advice! I have made some edits and taken out a ton of extra code (getters and setter. I learned with java...) and I have gotten the program to compile and work as intended save for a small but important issue.
No instance of constructor "Package::Package" matches the argument
list argument types are: (EndPoint, EndPoint, double, double)
in your code:
Package regular{ homer, donald, 25.0, 0.20 }; you are passing wrong variables to the constructor's parameters which is an Endpoint object for first and second parameter
what you have is:
Package(const std::string&, const std::string&, double = 0.0, double = 0.0);
which accepts a std::string object for first and second parameter.
cannot convert from 'initializer list' to 'Package
fixing problem 1 will fix this
i dont know why you get 3rd one since you have iomanip in your main

Object pointer doesn't work

My task was to create an object in class, initialize it and output(using pointer to class). This code compiles perfectly, but the output doesn't appear. I would really appreciate any help, thank you in advance!
#include <iostream>
#include <string>
using namespace std;
class family
{
public:
void setWife(string w)
{w = wife;};
string getWife()
{return wife;};
void setHusband(string h)
{husband = h;};
string getHusband()
{return husband;};
void setSon(string s)
{s = son;};
string getSon()
{return son;};
void setDaughter1(string d1)
{d1 = daughter1;};
string getDaughter1()
{return daughter1;};
void setDaughter2(string d2)
{daughter2 = d2;};
string getDaughter2()
{return daughter2;};
double* getPointer()
{return &pointer;};
void initialize()
{
setWife("Shirley Collin");
setHusband("Donald Collin");
setSon("Collin Collin");
setDaughter1("Harriet Collin");
setDaughter2("Hillary Collin");
}
friend void output(family* Collin);
private:
string wife;
string husband;
string son;
string daughter1;
string daughter2;
double pointer;
};
void output(family* Collin)
{cout << "Husband is " <<Collin->getHusband()<< endl;
cout << "wife is " << Collin ->getWife() << endl;
cout << "son is " << Collin->getSon() << endl;
cout << "daughter1 is " << Collin->getDaughter1() << endl;
cout << "daughter2 is " << Collin->getDaughter2()<< endl;
};
int main()
{family Collin;
Collin.initialize();
family *pointer = new family;
output (pointer);
cin.ignore();
}
family Collin;
Collin.initialize();
This constructs an instance of the family class, and initializes it with the values defined in the initialize() method.
family *pointer = new family;
output (pointer);
This constructs a second instance of the family class, does not initialize it in any way, and calls the output() method, to display the contents of the completely uninitialized second instance of this family class.
This is why this program produces no useful output.
You probably want to replace these four lines with:
family *pointer=new family;
pointer->initialize();
output(pointer);

Retrieving values of an object from an array?

Pardon the example but in this case:
#include <iostream>
#include <string>
using namespace std;
class A {
private:
string theName;
int theAge;
public:
A() : theName(""), theAge(0) { }
A(string name, int age) : theName(name), theAge(age) { }
};
class B {
private:
A theArray[1];
public:
void set(const A value) {theArray[0] = value; }
A get() const { return theArray[0]; }
};
int main()
{
A man("Bob", 25);
B manPlace;
manPlace.set(man);
cout << manPlace.get();
return 0;
}
Is it possible for me to retrieve the contents of the "man" object in main when I call manPlace.get()? My intention is to print both the name (Bob) and the age (25) when I call manPlace.get(). I want to store an object within an array within another class and I can retrieve the contents of said array within the main.
You need to define a ostream::operator<< on your A class to accomplish that - otherwise the format how age and name should be generated as text-output is undefined (and they are private members of your A class).
Take a look at the reference for ostream::operator<<. For your A class, such a operator could be defined like this:
std::ostream& operator<< (std::ostream &out, A &a) {
out << "Name: " << a.theName << std::endl;
out << "Age: " << a.theAge << std::endl;
return out;
}
Which would output something like:
Name: XX
Age: YY
So your complete code would be:
#include <iostream>
#include <string>
using namespace std;
class A {
private:
string theName;
int theAge;
public:
A() : theName(""), theAge(0) { }
A(string name, int age) : theName(name), theAge(age) { }
friend std::ostream& operator<< (std::ostream &out, A &a) {
out << "Name: " << a.theName << std::endl;
out << "Age: " << a.theAge << std::endl;
return out;
}
};
class B {
private:
A theArray[1];
public:
void set(const A value) { theArray[0] = value; }
A get() const { return theArray[0]; }
};
int main()
{
A man("Bob", 25);
B manPlace;
manPlace.set(man);
cout << manPlace.get();
return 0;
}
which will output:
Name: Bob
Age: 25