我有一个关于多态性和其他技术的问题。考虑以下方案:
#include <vector>
#include <memory>
using namespace std;
struct Base
{ };
struct Derived : Base
{ };
class group
{
private:
vector< unique_ptr<Base> > V;
public:
group( /* what to put here? */ )
: V( /* again: how to construct V? */ )
{ }
}
在这里,我有三个类:一个基类,称为Base
;一个派生类,称为Derived
; 最后一个类 ,group
将充当保存Base
指针的包装器。但我想实现以下目标:
使用移动语义。不应该涉及副本。调用者应该能够给构造函数几个临时对象,因为构造函数会窃取它们:
group my_wonderful_group( Base( /* parameters */ ) , Derived ( /* ... */ ) , Derived ( /* ... */ ) );
在初始化
V
列表中初始化。这样,V
可以是const限定的(尽管在初始化列表中初始化成员对象具有所有其他好处)。
我尝试了几件事,但它们要么看起来不合适,要么在概念上与我的目标相去甚远:
initializer_list
s' 元素是不可移动的;unique_ptr
s 是可移动的。- 可变参数模板似乎无法满足制作
V
const的目标。由于initializer_list
s 不能容纳不同类型的对象(就像vector
s 一样),所以我首先想到了它们,但是,如何?在阅读了许多示例之后,我仍然无法弄清楚如何制作可变参数模板构造函数,或者即使可以在没有解决方法的情况下这样做(即:创建一些init()函数,它需要 aBase
, aDerived
,...玩它)。 - 创建一个函数,该函数返回
unique_ptr<Base>
并将其参数转发给 的构造函数Derived
,从而充当类的用户友好包装器group
。然而,这确实没有什么意义,正如我用下面附加的代码说明的那样。
这就是我所拥有的:
#include <string>
#include <vector>
#include <memory>
#include <initializer_list>
#include <iostream>
using namespace std;
struct Base
{
string s;
Base(Base && b) : s(move(b.s)) { }
Base(const string & S) : s( S ) { }
};
struct Derived : Base
{
Derived(const string & S) : Base( S ) { }
};
unique_ptr<Base>
BASE ( const string & S )
{
return unique_ptr<Base>( new Base(S) );
}
unique_ptr<Base>
DERIVED ( const string & S )
{
return unique_ptr<Base>( new Derived(S) );
}
class C
{
private:
vector< unique_ptr<Base> > V;
public:
template<typename ... T>
C
( T ... t ) : V({ t... })
{ }
void
print
( void )
{
for ( const auto & x : this->V )
cout << x->s << endl;
}
;
};
int main(void)
{
C c( BASE("hola") , DERIVED("der1") , DERIVED("bor3") );
c.print();
return 0;
}
但是,它抱怨unique_ptr
调用 [deleted] 复制构造函数的使用,当构造函数中的参数包group
被扩展并以逗号分隔放入initializer_list
将用于初始化的 中时V
。
我想我的问题归结为 a vector
,事实上,可以应用于一个:vector<unique_ptr<Base>>( /* initialize with derived classes */ )
。我认为这一定已经解决了,因为多态是基本的 C++,并且持有派生类的对象似乎是它的一种非常常见的用法。作为说明,我使用g++ 4.8.1
.
提前致谢。最好的问候, Kalrish
PS:我刚刚阅读了这个似乎部分涵盖了我的问题的问题。