class A, B;
class A {
public:
A& operator= ( const A &rhs ) { return *this; }
};
class B: public A {
public:
B& operator= ( const A &rhs ) { return *this; }
};
A a;
B b;
std::list < A > aa;
std::list < B > bb;
a = b; // works
b = a; // works
// aa = bb; // fails
// bb = aa; // fails
如何让bb = aa工作?
答案 0 :(得分:6)
您在此处遗漏的是,即使A
和B
是相关类型,std::list<A>
和std::list<B>
实际上是不相关的类型(除了两者都说list
)。因此,您无法使用复制分配在它们之间进行分配。
但是,假设您可以使用其分配运算符为彼此分配类型A
和B
,则可以使用list
&#39; s {{ 1}}复制迭代器范围的方法:
assign
答案 1 :(得分:4)
您可以使用copy
和back_inserter
:
std::copy(aa.begin(), aa.end(), back_inserter<list<B>>(bb));
但是在可以从源元素(这里是A)构造目标元素(这里是B)的条件下。所以在这里,你需要一个基于A对象的B构造函数。
注意:如果您没有在目标类中拥有复制所需的构造函数,但是您还有其他方法可以从源构建目标对象,则可以考虑使用std::transform()
顺便提一下,注意:a=b
有效,但可能会导致slicing。
答案 2 :(得分:3)
您可以将mySring = "abc==abc++abc==bc++abc";
String[] splitString = myString.split("\\W+");
类型的对象分配给ParseQuery query = new ParseQuery("Child");
query.fromLocalDatastore();
query.findInBackground(new FindCallback<ParseObject>() {
@Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
removeAllViews(pager);
children.clear(); //Clear it out before we regen every person!
for (int i = 0; i < objects.size(); i++) {
ChildInfo child = new ChildInfo();
child.name = objects.get(i).getString("Name");
child.gradeLevel = objects.get(i).getString("GradeLevel");
child.gradeLevelInt = objects.get(i).getInt("GradeLevelInt");
children.add(child);
}
Log.i("HomePagerAdapter", "Children Size: " + children.size() + "\n Obj Size: " + objects.size());
for (int i = 0; i < children.size(); i++) {
addChild(pager, children.get(i).name, children.get(i).gradeLevelInt);
}
} else {
Log.e("HomePagerAdapter", e.toString());
}
}
});
类型的对象,但这并不代表A
和B
的保留。
而不是你可以使用list<A>
:
list<B>
编辑:为了使用它,您必须先调用std::copy
,或者更好地使用@Christophe所述的std::copy(bb.begin(), bb.end(), std::back_inserter(aa)); // instead of aa = bb
。
你应该清楚你在这里做了什么:它要么切片(aa.resize(bb.size())
)要么指定一个非最终类(back_inserter
)。为了避免这种情况,您应该使用指针并使用克隆模式。
答案 3 :(得分:2)
就编译器而言std::list<A>
和std::list<B>
是不相交的类型。如果您认为std::list
已在内部为A
个对象分配内存,则这是有意义的。试图将B
个对象分配到该空间可能很灾难。
想象一下,例如,B有一个额外的属性。现在,如果您尝试将B
存储到足够A
的内存中,则可能不合适。可以使用类似的逻辑来查看另一个方向也失败的原因:如果将A
存储到B
的空间中,编译器会期望它所信任的B
的额外属性在那个空间是有效的。如果你分配了一个A
,那个空间里面有谁知道什么。
如果您希望此分配能够工作,您将需要使用某种形式的间接。例如,您可以使用两个std::list<A*>
个实例或两个std::list<std::shared_ptr<A>>
个实例。这可行,因为B*
可以安全地视为A*
,至少假设这些类已正确编写。
答案 4 :(得分:1)
我认为没有人真正试图回答如何分配bb = aa;
的问题
如前所述,您不能将std::list<B>
的隐式强制转换或赋值运算符定义为自由运算符。但你有两个选择。他们都依赖于对这个集合进行子类化......只要你不允许任何其他状态就可以了。
选项#1,将BB
定义为std::list<B>
的子类,bb
将使用这些类。 (BB
将获得一个额外的赋值运算符。)
选项#2,是使用辅助类,并且可能更接近您的原始意图。辅助类将定义为上述BB
类,将隐式转换运算符添加回std::list<B>
。
完整的例子如下:
class A {};
class B: public A {
public:
B() = default;
B( const A &rhs ) {} // Empty because A and B are not defined with any state.
B& operator= ( const A &rhs ) { return *this; }
};
class BB : public std::list<B> {
public:
BB() = default;
BB(const std::list<A> &aa) { assign( aa.begin(), aa.end() ); }
BB& operator= ( const std::list<A> &rhs ) { assign(rhs.begin(), rhs.end()); return *this; }
operator std::list<B>() { return *this; }
};
// No new member variables or virtual methods are allowed.
static_assert( sizeof (std::list<B>) == sizeof (BB), "Bad derivation of std::list<B>" );
A a;
B b;
b = a; // works
std::list<A> aa;
std::list<B> bb;
BB helper;
bb = helper = aa; // Option #2; bb is std::list<B>
或者您可以直接使用BB
:
BB bb = aa; // Option #1; use bb just like std::list<B>