复制具有 const 向量成员的类的构造函数

Copy constructor of a class with a const vector member

提问人:Barak B 提问时间:11/8/2018 最后编辑:Pika Supports UkraineBarak B 更新时间:11/9/2018 访问量:856

问:

我的代码中有这个类:OpenTable

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;
};

我需要为这个类实现一个复制构造函数(我知道这可能是一个糟糕的设计,但我被指示这样做)。我在尝试深度复制常量向量时遇到了问题。customers

我尝试了以下方法:

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*
    }

但显然它没有编译,可能是因为向量是 ,因此我无法向它添加元素。const

我收到以下错误:

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 *>>

注意:在参数化构造函数中,我只是浅层复制,因为我可以。不过,这不适用于复制构造函数。

提前致谢。

C++ 常量 复制构造函数

评论

0赞 Some programmer dude 11/8/2018
是多态基类吗?如果不是,为什么需要指针?如果你需要指针,你有没有考虑过所有权语义,也许用 std::shared_ptr 共享对象的所有权CustomerCustomer
1赞 François Andrieux 11/8/2018
const数据成员几乎从来都不值得麻烦。
3赞 Peter 11/8/2018
创建一个帮助程序函数(如果要限制对它的访问,它可以是类的成员)并返回深层副本。然后,在构造函数的初始化器列表中,使用它来初始化私有成员。privatestaticconst std::vector<Customer *>std::vector<Customer *>
1赞 Caleth 11/8/2018
@BarakB可以调用不依赖于(尚未初始化的)成员数据的非虚拟成员。成员很容易满足这些标准static
1赞 Caleth 11/9/2018
顺便说一句,更改指针将使为您的类提供异常保证变得更加容易std::unique_ptr<Customer>

答:

1赞 Caleth 11/8/2018 #1

您将需要类似 boost::transform_iterator 的东西来执行复制作为成员初始化器的一部分。

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()))
{}

或者交替

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(); })))
{}
0赞 AD1170 11/9/2018 #2

为什么使用 const 类 memebers?你对他们无能为力。改为将公共访问功能设置为只读。

std::vector<Customers *> const getCustumers() const { return customers;}
int const getTableId() const { return tableId; }

这将为您提供客户的只读向量或无法修改的表 ID。比复制结构是没有问题的。

2赞 Peter 11/9/2018 #3

最简单的解决方案是创建一个帮助程序函数,该函数接受 a 并返回 a 作为参数的深层副本。然后,在构造函数的初始化器列表中,使用该函数初始化私有成员。const std::vector<Customer *>std::vector<Customer *>

(可选)如果要限制对类的访问,则该帮助程序函数可以是类的 和 成员。这在构造函数或其初始化器列表中是可以接受的,因为成员函数不依赖于正在初始化的类的非静态成员,因此不依赖于已完成的构造函数。privatestaticstatic

如果在进行深度复制的帮助程序函数中出现问题,则需要适当地清理帮助程序函数(例如,如果其中一个对象的构造失败,则需要释放任何成功构造的对象以避免内存泄漏)。Customer