我的目标是能够创建一个对象与不同类型的成员对象来自同一个类族;在Java
中,它看起来像这样:
public class Interface {
public void test();
}
public class MyImpl1 implements Interface {
@Override
public void test() {System.out.println("I am impl 1");}
}
public class MyImpl2 implements Interface {
@Override
public void test() {System.out.println("I am impl 2");}
}
public class A {
public A(Interface myinter) {
_myinter = myinter;
}
Interface _myinter;
}
这样我就可以创建一个具有不同实现的对象:
A a(new MyImpl1());
或
A a(new MyImpl2());
(对不起,如果有语法错误在这个拙劣的代码,这只是为了解释我想要的)
所以,在c++中,我想我会用智能指针实现这一点,以受益于RAII。因此,我编写了以下代码:
#include <iostream>
#include <memory>
using namespace std;
struct Interf {
virtual void test() {cout << "I am Interf" << endl;}
};
struct A {
A(std::unique_ptr<Interf> e) : _e(std::move(e)) {}
std::unique_ptr<Interf> _e;
void test() {_e->test();}
};
struct Impl : public Interf {
void test() {cout << "I am Impl;" << endl;}
};
int main()
{
std::unique_ptr<Interf> b(new Impl);
A a(std::move(b));
a.test();
cout << "fine!" << endl;
return 0;
}
我似乎在工作。但是,这是实现它的正确方法吗?还是有错误,还是更好的实践?
此外,在此代码中,我不确定是否需要使用
std::move
两次。这是传递unique_ptr
到构造器的正确方法吗?另一件事我不明白的是为什么这段代码不编译,如果我删除
_e(std::move(e))
从成员初始化列表,并把内部构造函数;谁能解释一下这是怎么回事?
.
struct A {
A(std::unique_ptr<Interf> e) {
_e(std::move(e));
}
...
};
有三个std::unique_ptr
传递你的Interf
:
-
b
,main()
中的局部变量; -
e
,A
的构造函数参数; -
_e
,A
实例的成员。
在三个不同的指针上移动Interf
实例需要两次连续的std::move()
操作(b
到e
,然后e
到_e
),这是完全有意义的。
稍微偏离主题:c++ 14鼓励使用std::make_unique
。这是c++ 11。
你的代码绝对没问题:)
编辑:成员变量只在成员初始化列表中初始化。在构造函数体中,_e(std::move(e));
意味着调用_e
的operator ()
,就好像它是一个函子一样。
分配给_e
应该与_e = std::move(e);
一起完成,尽管直接初始化它总是更好。