Reputation: 84
I have the class OpenTable
in my code:
class OpenTable : public BaseAction {
public:
OpenTable(int id, std::vector<Customer *> &customersList);
OpenTable(const OpenTable& other);
private:
const int tableId;
const std::vector<Customer *> customers;
};
I need to implement a copy constructor for this class (I know it's probably a bad design, but I was instructed to do so). I ran into a problem when trying to deep copy the const vector customers
.
I tried the following:
OpenTable::OpenTable(const OpenTable& other): tableId(other.tableId)
{
for(std::vector<Customer*>::const_iterator i=other.customers.begin(); i!=other.customers.end(); i++) {
customers.push_back((*i)->copy()); // copy returns a Customer*
}
But clearly it doesn't compile, probably because the vector is const
, thus I can't add elements to it.
I get the following error:
no instance of overloaded function "std::vector<_Tp, _Alloc>::push_back
[with _Tp=Customer *, _Alloc=std::allocator<Customer *>]" matches the
argument list and object (the object has type qualifiers that prevent a
match) -- argument types are: (Customer *) -- object type is: const
std::vector<Customer *, std::allocator<Customer *>>
Note: In the parameterized constructor I simply shallow copied because I could. This won't work for the copy constructor though.
Thanks in advance.
Upvotes: 1
Views: 1015
Reputation: 36597
The simplest solution would be to create a helper function that accepts a const std::vector<Customer *>
and returns a std::vector<Customer *>
that is a deep copy of the argument. Then, in the initialiser list of your constructor, use that function to initialise your private member.
Optionally, that helper function can be a private
and static
member of your class if you want to limit access to it. That is acceptable in a constructor or its initialiser list, since a static
member function does not rely on non-static members of class being initialised, so does not rely on the constructor having completed.
If a problem occurs in the helper function making the deep copy, the helper function will need to clean up appropriately (e.g. if construction of one of the Customer
objects fails, any successfully constructed objects will need to be released to avoid a memory leak).
Upvotes: 2
Reputation: 418
Why you use const class memebers? You can nothing do with them. Make the public access funtions read only instead.
std::vector<Customers *> const getCustumers() const { return customers;}
int const getTableId() const { return tableId; }
This will give you a read only vector of customers or a table id that can't be modifyed. Than the copy constuctor is no problem.
Upvotes: 0
Reputation: 62636
You are going to need something like boost::transform_iterator
to do the copying as part of the member initialiser.
auto copy_iter(auto iter)
{
return boost::make_transform_iterator(iter, [](Customer * c){ return c->copy(); });
}
OpenTable::OpenTable(const OpenTable& other)
: tableId(other.tableId),
customers(copy_iter(other.customers.begin()), copy_iter(other.customers.end()))
{}
or alternately
OpenTable::OpenTable(const OpenTable& other)
: tableId(other.tableId),
customers(boost::copy_range<std::vector<Customer *>>(other.customers | boost::adaptors::transformed([](Customer * c){ return c->copy(); })))
{}
Upvotes: 1