Using vector with derived classes - c++

I'm trying to use a vector for derived class Employee but I got en error:
class Company : public Employee, public TesterEmployee, public DeveloperEmployee {
private:
std::vector<Employee*> _table;
public:
friend std::vector<Employee*>& operator+=(const Employee* emp) {
_table.push_back(emp->clone());
return *this;
}
};
The error is:
error: 'std::vector<Employee*>& operator+=(const Employee*)' must have an argument of class or enumerated type

+= is a binary operator. The function
friend std::vector<Employee*>& operator+=(const Employee* emp) {
_table.push_back(emp->clone());
return *this;
}
defines a non-member function that can take only one argument. Hence, it cannot be used in an expression like:
a += b;
What you need is:
Company& operator+=(const Employee* emp) {
_table.push_back(emp->clone());
return *this;
}

In response to the other question about the same code (that you deleted https://stackoverflow.com/questions/30717107/operator-overloading-in-my-class-with-error):
Q and the problem :
error: invalid operands of types 'Company*' and 'DeveloperEmployee*' to binary 'operator+'|
What does it mean?
It means you're trying to write Java/C# code in C++. Don't do that.
In particular you're abusing OOP for the sake of OOP. A Company is-not-a Employee (see Liskov), and company + employee doesn't make sense.
Lose the new.
Lose the base class.
Probably lose the clone based dynamic value semantics.
Finally, your problem is, you're using operator+= which you didn't overload.
Live On Coliru
#include <vector>
#include <iostream>
struct Employee {
int getID() const { return _id; }
private:
int _id = generate_id();
static int generate_id() {
static int next = 0;
return ++next;
}
};
struct DeveloperEmployee : Employee {
DeveloperEmployee(std::string const& descr, std::string const& project)
: _description(descr), _project(project) { }
private:
std::string _description;
std::string _project;
friend std::ostream& operator<<(std::ostream& os, DeveloperEmployee const& de) {
return os << "id:" << de.getID() << " descr:'" << de._description << "' project:'" << de._project << "'";
}
};
class Company {
private:
std::vector<Employee> _table;
std::string _des;
public:
Company &operator+=(const Employee &emp) {
_table.push_back(emp);
return *this;
}
void setDescription(std::string des) { _des = des; }
};
int main() {
Company company;
DeveloperEmployee a("description", "project");
int id = a.getID();
std::cout << a << std::endl; // Developer ID = 2, project = hw5
company += a;
}

Related

Custom set comparison function in a template class

I was trying to figure out this exercise from a school exam.
They implemented an abstract template Book class, and the assignment is to implement a bookshelf class.
I tried to construct a set of book pointers with a custom comparator, but then I encounter a compilation error:
In template: reference to type 'const Book<std::basic_string<char>>' could not bind to an lvalue of type 'const std::_Rb_tree<...>
(I implemented a sub class BOOK2 just for debugging purposes)
This is the long given book abstract class
#include <iostream>
#include <set>
#include <string>
#include <utility>
template <class T>
class Book
{
// any member variables are inaccessible to descendants
private:
std::string _title; // do not call a copy-ctr
T _author; // do not call a copy-ctr
size_t _number_of_pages;
public:
Book(std::string title,
T author,
size_t number_of_pages)
: _title(std::move(title)),
_author(std::move(author)),
_number_of_pages(number_of_pages)
{}
virtual ~Book() = default;
const std::string& get_title() const
{ return _title; }
const T& get_author() const
{ return _author; }
size_t get_number_of_pages() const
{ return _number_of_pages; }
public:
virtual Book<T>* clone() const = 0; // implemented *only* by descendent classes
virtual bool is_available_on(const std::string& platform) const = 0; // implemented *only* by descendant classes
protected:
virtual void do_output(std::ostream& os) const // can be overridden; can be accessed *only* by descendants
{
os << _title << ", " << _author << ", " << _number_of_pages << " pages";
}
// output should depend on who book really is
friend std::ostream& operator<<(std::ostream& os, const Book& book)
{
book.do_output(os);
return os;
}
};
This is what I implemented:
class Book2: public Book<std::string>{
public:
Book2(std::string &title,
std::string &author,
size_t number_of_pages)
: Book<std::string>(title,author,number_of_pages){}
bool is_available_on(const std::string &platform) const override{return
true;}
Book<std::basic_string<char>> * clone() const override{
Book<std::basic_string<char>> * a{};
return a;
}
};
template<class TP>
static bool book_comp(const Book<TP>& a,const Book<TP> & b){
return a.get_title()<b.get_title();}
template<class TT>
class Bookshelf
{
public:
typedef bool(*book_comp_t)(const Book<TT>& a,const Book<TT> & b);
// DO NOT CHANGE NEXT TWO LINES:
auto& get_books() { return _books; } // DO NO CHANGE
auto& get_books() const { return _books; } // DO NO CHANGE
Bookshelf():_books(book_comp<TT>){}
void add(Book<TT>& book)
{
size_t init_size=_books.size();
_books.insert (&book);
if(init_size==_books.size()){
throw std::invalid_argument("book already in bookshlf");
}
}
// sorted lexicographically by title
friend std::ostream& operator<<(std::ostream& os, const Bookshelf<TT>&
bookshelf)
{
for(const auto& book :bookshelf._books)
{
os << *book << std::endl;
}
}
private:
std::set<Book<TT>*,book_comp_t> _books;
};
int main ()
{
std::string a ="aba";
std::string bb ="ima;";
Book2 b = Book2(a, bb, 30);
Bookshelf<std::string> shelf;
std::cout<<b;
shelf.add(b);
}
I tried changing the const qualifiers in some places, and it didn't work.
I also tried without using the custom comparator function which worked ok.
I think this is probably some syntax error maybe?
std::set<Book<TT>*,book_comp_t> _books; is a set of Book<TT>*, and thus requires a comparator whose parameters are of type Book<TT>*, not const Book<TT>&

Overload += for a template?

I have a base class Animal and a derived class Bird : Animal. I use a template class that will store vectors of pointers to either Animal or Bird objects. I want to overload the += operator in such a way that I can insert a new animal right in the Atlas, so m_length = m_length + 1, pages.push_back(animal), just to get the idea.
Here's my template class:
template <class T>
class Atlas2 {
public:
int m_length;
std::list<T> pages;
Atlas2() { m_length = 0; }
~Atlas2() {}
void adauga(T data);
T operator+=(const T& data) {
this->m_length++;
this->pages.push_back(data);
return *this;
};
};
And here's the Animal/Bird classes:
class Animal {
protected:
std::string m_name;
public:
Animal() {}
Animal(std::string name) : m_name{name} {}
virtual void set_name(std::string name) { m_name = name; }
virtual std::string get_name() { return m_name; }
virtual std::string regn() const { return "???"; }
virtual ~Animal() { cout << "Destructor animal" << '\n'; }
};
class Bird : public Animal {
public:
bird() : animal() {}
bird(std::string name) : Animal{name} {}
void set_name(std::string nume) { m_name = nume; }
std::string get_name() { return m_name; }
std::string regn() const override { return "pasare"; }
~bird() { cout << "destructor pasare" << '\n'; }
};
However, I can't figure this out. When I use the overloaded += operator in main() like this:
Pasare *c = new Pasare{"vulture"};
Atlas2<Animal *> Atlas;
Atlas += c;
It shows me an error, that it couldn't convert Atlas<Animal *> to <Animal*>.
How should I implement this correctly? Any tip?
Note: The template works fine, I can store in my list pointers to either Animal or Birds without problems, and access their specific methods. I just can't figure out the += part.
You should return Atlas2<T> & not T:
Atlas2<T>& operator+=(const T& data) {
this->m_length++;
this->pagini.push_back(data);
return *this;
};
The basic problem is that you've declared your operator+= as returning a T, but the return statement in it is return *this;, which is an Atlas2<T>.
If you change the return type to Atlas2<T> &, it should work. That's what you would normally want to return from an operator+= anyways, though with your use, it doesn't matter much as you're ignoring the returned value.

How to make a data member of a class unique for each instance of that class

This is the code of the program I have written and everything works just perfectly except the part that it has only one requirement. The ID data member of the class Department should be unique for each instance of that class. I have tried using operator overloading to compare the IDs of the Departments created. But the problem with that would be that the comparison should be made in the main driver of the program, and it is required to be made either in the constructor of the class or inside the class.
Here is the code
class Department {
public:
Department(string id) {
ID = id;
}
bool operator== (const Department& rhs) {
return ID == rhs.ID;
}
friend ostream& operator<<(ostream& out, const Department& value);
protected:
string ID;
};
ostream& operator<<(ostream& out, const Department& value)
{
out << value.ID;
return out;
}
int main() {
Department d1("ID-1");
Department d2("ID-1");
if (d1 == d2) {
cout << "They are the same";
}
else {
cout << "No the same";
}
}
You can make a static attribute that is incremented after each assignment. The static attribute will be the same for all instances.
This may be what the previous answer is intending, though this one increments whenever an object is constructed. That way each object is given essentially a new serial number when it comes to life.
class Department {
public:
Department() {
ID = "ID_" + std::to_string(IDcount);
++IDcount;
}
bool operator== (const Department& rhs) {
return ID == rhs.ID;
}
protected:
string ID;
static int IDcount;
};
int Department::IDcount = 0;
To ensure that no two instances of a class have the same value for a data-member, you can make its constructor non-public and use a singleton friend class to manage its instances.
class Department
{
protected:
string ID;
friend class DepartmentCreator;
Department(string id)
{
ID = id;
}
Department();
};
class DepartmentCreator
{
private:
map<string, Department *> dept_instances;
static DepartmentCreator *this_instance;
DepartmentCreator();
public:
DepartmentCreator(const DepartmentCreator &) = delete;
void operator=(const DepartmentCreator &) = delete;
static DepartmentCreator *GetCreator();
Department *GetDepartment(string id);
};
DepartmentCreator *DepartmentCreator::this_instance = nullptr;
DepartmentCreator::DepartmentCreator() {}
DepartmentCreator *DepartmentCreator::GetCreator()
{
if (!this_instance)
{
this_instance = new DepartmentCreator();
}
return this_instance;
}
Department *DepartmentCreator::GetDepartment(string id)
{
if (dept_instances.find(id) == dept_instances.end())
{
dept_instances[id] = new Department(id);
}
return dept_instances[id];
}
Now, you can use it like this:
DepartmentCreator *dept_creator = DepartmentCreator::GetCreator();
Department *d1 = dept_creator->GetDepartment("ID-1");
Department *d2 = dept_creator->GetDepartment("ID-1");
There is no need to overload ==. You will always get the same pointer for a given ID.

C++ Inheritance operator<<

I have a few objects (classes) that all inherit from a base class Structure. These objects all print differently as they have different member variables but share common functions.
I want to be able to have a list of structures and print them without having to cast them back into their specific object, ie: Structure -> Building.
Is this possible in C++?
class Structure
{
};
class Building : public Structure
{
public:
friend std::ostream& operator<<(std::ostream& o, const Building &b)
{
return o << b.m_windows.size() << b.m_doors.size();
}
protected:
Windows m_windows;
Doors m_doors;
};
class Statue : public Structure
{
public:
friend std::ostream& operator<<(std::ostream& o, const Statue &s)
{
return o << s.m_type;
}
protected:
StatueType m_type;
};
int main(int argc, char* argv[])
{
Structure struct* = new Building();
std::cout << struct << std::endl;
return 0;
}
Error:
error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
std::cout << struct << std::endl;
Edit:
I've isolated the issue in my own code, here is a compilable version (C11). The problem is that I am using further inheritance and the output of my command is:
CORRECT_VALUE<random address>
8.8.8.80x804c504
I'm not sure why it appends that random address?
http://pastebin.com/81ubU0yX
Create a virtual output function and call it within the operator <<. Override this output function in your derived classes.
class Structure
{
public:
virtual ~Structure() {}
virtual std::ostream& StreamOut(std::ostream& o) const { return o; }
friend std::ostream& operator<<(std::ostream& o, const Structure &s)
{
return s.StreamOut(o);
}
};
class Building : public Structure
{
public:
virtual std::ostream& StreamOut(std::ostream& o) const
{
return o << m_windows.size() << m_doors.size();
}
protected:
Windows m_windows;
Doors m_doors;
};
class Statue : public Structure
{
public:
virtual std::ostream& StreamOut(std::ostream& o) const
{
return o << m_type;
}
protected:
StatueType m_type;
};
int main(int argc, char* argv[])
{
std::unique_ptr<Structure> myStruct(new Building());
std::cout << *myStruct << std::endl;
}

Generic output operator overloading with inheritance

Given an abstract base class Object and 2 derived classes, Person and Gathering. Where Gathering is a data structure which stores pointers to Person or other Gathering pointers inside of an array.
I would like to override the output operator so it prints any type of Object. But I do not know how to override the operator properly so when it receives type Object it knows how to deal with it.
Here is a simple code that exemplifies what I'm trying to achieve:
#import <iostream>
#import <cstring>
class Object {
public:
virtual ~Object(){};
};
class Person : public Object {
private:
char * m_name;
public:
Person(char * input) {
m_name = new char[strlen(input)];
strncpy(m_name, input, strlen(input));
}
char* getName() const{
return m_name;
}
friend std::ostream& operator<<(std::ostream& os, const Person* p) {
os << p->getName();
return os;
}
};
class Gathering : public Object {
private:
int m_size;
Object* m_buffer;
public:
Gathering() : m_size(10)
{}
friend std::ostream& operator<<(std::ostream& os, const Gathering* v) {
for (int i=0; i<v->getSize(); i++) {
//Trying to send Object to outputstream..
os << "[" << v->getBuffer()[i] << "]";
}
}
int getSize() const {
return m_size;
}
Object* getBuffer() const {
return m_buffer;
}
};
I am very aware of what the problem is, how do Ideal with this? Any references or pointers are very appreciated.
You can add a virtual member function in Object, call it in your operator overload and implement it correctly for children classes.
class Object {
public:
virtual ~Object(){}
virtual void print(std::ostream&){}
friend std::ostream& operator<<(std::ostream& os, const Object& obj) {
obj.print(os);
return os;
}
};
class Gathering : public Object {
private:
int m_size;
Object* m_buffer;
public:
Gathering() : m_size(10)
{}
virtual void print(std::ostream& os) {
for (int i=0; i<v->getSize(); i++) {
os << "[";
m_buffer[i].print(os);
os << "]";
}
}
int getSize() const {
return m_size;
}
Object* getBuffer() const {
return m_buffer;
}
};
Also not related, but put a virtual destructor in your children classes, use a vector instead of your Object pointer m_buffer or at least initialise it in your constructor, but i guess you have school restrictions or something :)