[英]c++ assignment operator= overloading with derived classes
I'm currently writing a complicated class and in it I basically need to copy a list of derived classes. 我正在编写一个复杂的类,在其中我基本上需要复制派生类的列表。 The simplified version is, as follows: I have a base class from which I derive several other classes:
简化版本如下:我有一个基类,我可以从中派生出其他几个类:
class Base
{
public:
virtual void test(void)
{
cout << "Base" << endl;
}
Base(vector<Base*> *pointer)
{
pointer->push_back(this);
}
virtual Base& operator=(const Base& rhs)
{
cout << "Base=" << endl;
return *this;
}
};
class A : public Base
{
public:
void test(void)
{
cout << "A" << endl;
}
A(vector<Base*> *pointer) : Base(pointer) {}
A& operator=(const A& rhs)
{
cout << "A=" << endl;
return *this;
}
};
class B : public Base
{
public:
void test(void)
{
cout << "B" << endl;
}
B(vector<Base*> *pointer) : Base(pointer) {}
B& operator=(const B& rhs)
{
cout << "B=" << endl;
return *this;
}
};
Then I create a list of objects, which I save in the in a pointer list of the Base class: 然后我创建一个对象列表,我将其保存在Base类的指针列表中:
vector<Base*> listA;
new Base(&listA);
new A(&listA);
new B(&listA);
These objects I then want to copy in a second list with the same classes (same order), but which might have different values. 然后,我想要在具有相同类(相同顺序)的第二个列表中复制这些对象,但这些对象可能具有不同的值。
for (int i = 0; i < (int)listA.size(); i++)
{
(*listA[i]) = (*listB[i]);
}
However c++ is not able to do that. 但是c ++无法做到这一点。 Because the list has the type Base*, dereferencing creates an object of type Base.
由于列表的类型为Base *,因此解除引用会创建Base类型的对象。 Therefore the assignment operator= of the Base class is called instead of the correct one from the derived class.
因此,从派生类调用Base类的赋值运算符=而不是正确的赋值运算符。 How can I fix this?
我怎样才能解决这个问题?
Or how can I tell c++ to use the right operator? 或者我如何告诉c ++使用正确的运算符? Maybe by some isinstanceof-function?
也许是某种功能?
For a full sample see: 如需完整样本,请参阅:
int main()
{
vector<Base*> listA;
new Base(&listA);
new A(&listA);
new B(&listA);
vector<Base*> listB;
new Base(&listB);
new A(&listB);
new B(&listB);
for (int i = 0; i < (int)listA.size(); i++)
{
(*listA[i]).test();
}
for (int i = 0; i < (int)listA.size(); i++)
{
(*listA[i]) = (*listB[i]);
}
}
Which outputs: 哪个输出:
Base
A
B
Base=
Base=
Base=
There are a few misunderstandings here. 这里有一些误解。 First and foremost, what does it mean to assign an instance of a derived class to an instance of a base class?
首先,将派生类的实例分配给基类的实例意味着什么? Let's take a simple hierarchy:
我们采取一个简单的层次结构:
struct A { int x; };
struct B : A { int y; };
A a;
B b;
a = b; // what should this do?
b = a; // what about this?
With normal C++, the first one does object slicing , and the second one is ill-formed. 使用普通的C ++,第一个进行对象切片 ,第二个进行异常切换 。 But even the first one, well well-formed, is typically not what you want to do anyway.
但即便是第一个,形状良好,通常也不是你想要做的。 Are you sure you want to be slicing?
你确定要切片吗?
The second is that while you made your assignment operator virtual: 第二个是,当您将赋值运算符设为虚拟时:
virtual Base& operator=(const Base& rhs)
None of the derived classes actually override it. 没有派生类实际覆盖它。
A
's assignment operator takes an A const&
and B
's takes a B const&
. A
's赋值运算符取一个A const&
而B
'取一个B const&
。 If you marked the two with override
, your compiler would point this out to you. 如果您使用
override
标记了两个,则编译器会将此指向您。 If you fix those two to take a Base const&
argument, then you would get what you want printed - but it's probably still not what you actually want to have happen. 如果你修复这两个以获取一个
Base const&
参数,那么你会得到你想要的东西 - 但它可能仍然不是你真正想要发生的。
In order to actually make polymorphic copies, a typical solution is to provide a virtual clone method: 为了实际制作多态副本,典型的解决方案是提供虚拟克隆方法:
virtual Base* clone() const = 0;
That your derived classes implement: 您的派生类实现:
struct A : Base {
A* clone() const override { return new A(*this); }
};
And then use clone()
instead of assignment. 然后使用
clone()
而不是赋值。 There will be no slicing here. 这里没有切片。
Insert the usual caveats about memory management and raw pointers here. 在此处插入有关内存管理和原始指针的常见警告。
Okay. 好的。 I found a solution for my problem.
我找到了解决问题的方法。 I implemented a copy function which takes the Base class as the argument.
我实现了一个以Base类为参数的复制函数。 Inside this copy function I can copy the variables using the
pointa
. 在这个复制函数中,我可以使用
pointa
复制变量。 The classe now are as follows: classe现在如下:
class Base
{
public:
virtual void test(void)
{
cout << "Base" << endl;
}
Base(vector<Base*> *pointer)
{
pointer->push_back(this);
}
virtual void clone(Base* pointer) = 0;
};
class A : public Base
{
public:
void test(void)
{
cout << "A" << endl;
}
A(vector<Base*> *pointer) : Base(pointer) {}
void clone(Base* pointer) override
{
A* pointa = (A*)pointer;
cout << "clone A" << endl;
//Clone Variables here
}
};
class B : public Base
{
public:
void test(void)
{
cout << "B" << endl;
}
B(vector<Base*> *pointer) : Base(pointer) {}
void clone(Base* pointer) override
{
B* pointa = (B*)pointer;
cout << "clone B" << endl;
//Clone Variables here
}
};
This means I can now copy the objects in the following way: 这意味着我现在可以通过以下方式复制对象:
for (int i = 0; i < (int)listA.size(); i++)
{
listA[i]->clone(listB[i]);
}
However this solution is not in any way typesafe, a requirement I want to meet. 然而,这个解决方案绝不是类型安全的,这是我想要满足的要求。 I looked into my idea, and decided to do things manually without the list, which means lot's of duplicated code, but brings peace of mind.
我调查了我的想法,并决定在没有列表的情况下手动执行操作,这意味着很多重复的代码,但带来了安心。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.