问题描述
我正在与一个工会合作,该工会的成员是使用菱形继承的类,但是该程序在分配给该成员时遇到分段错误。
我怀疑我需要添加一些副本构造函数,但是经过多次尝试,执行此操作的正确方法仍然使我不知所措。
我在此处提供了一个最小的,可重复的示例。
struct Base
{
Base() : a(0) {}
Base(int x) : a(x) {}
int a;
};
struct Derived1 : virtual public Base
{
Derived1() {}
};
struct Derived2 : virtual public Base
{
Derived2() {}
};
struct Final : public Derived1,public Derived2
{
Final() {}
};
union Example
{
Final value;
int i;
};
int main()
{
Example example{ Final() };
example.i = -1;
/* Segfault on the line below.
* If the above line
example.i = -1;
* is removed,the segfault is not encountered. */
example.value = Final();
}
我感谢所有知道该怎么做的人。
解决方法
由于@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (ctx) => Authentication(),),ChangeNotifierProvider(
create: (ctx) => Books(),ChangeNotifierProvider(
create: (ctx) => HomeProvider(),ChangeNotifierProvider(
create: (ctx) => Renk(),],child: MaterialApp(
类为virtual,因此很可能有些内部控制结构在分配时会被破坏
Base
例如,当您重新创建example.i = -1;
时
value
在分配之前,分段错误消失了。虽然,我不推荐这种黑客攻击。
正如注释中已经提到的,如果您有C ++ 17,那么std::variant
会更合适。该示例将变为
new(&example.value) Final();
example.value = Final();
,
从c ++ 11开始,与定义自己的构造函数的成员进行联合 和/或复制控制成员是允许的,但是当一个联合具有内置类型的成员时,我们可以使用普通分配来 更改工会持有的价值,但不更改具有以下成员的工会的价值 非平凡的类类型。当我们将联盟的价值与成员之间进行切换时 类类型,我们必须构造或销毁该成员。例如看下面的代码
#include <iostream>
#include <new> // for placement new
class Type // non built in type with constructors
{
private:
int val;
public:
Type() : val{0} { }
explicit Type(int v) : val{v} { }
Type(const Type &obj) : val{obj.val} { }
int getval() { return val; }
};
class unionexample // I enclose union with class for readability
{
private:
enum { INT,TYPE } OBJ;
union
{
Type Tval; // non build in type
int ival; // build in type
};
public:
unionexample() : ival{0},OBJ{INT} // default with int
{ }
unionexample(const unionexample &obj) : OBJ{obj.OBJ}
{
switch (obj.OBJ)
{
case INT:
this->ival = obj.ival;
break;
case TYPE:
new (&this->Tval) Type(obj.Tval);
break;
}
}
unionexample &operator=(int v)
{
if (OBJ == TYPE)
{
Tval.~Type(); // if it is TYPE destruct it
}
ival = v; // assign
OBJ = INT;
return *this;
}
unionexample &operator=(Type v)
{
if (OBJ == TYPE)
{
Tval = v; // if it is alderdy Type just assign
}
new (&Tval) Type(v); // else construct
OBJ = TYPE;
return *this;
}
void print()
{
switch (OBJ)
{
case INT:
std::cout << "ival = " << ival << std::endl;
break;
case TYPE:
std::cout << "Tval = " << Tval.getval() << std::endl;
break;
}
}
~unionexample()
{
if (OBJ == TYPE) // if it is TYPE we must destruct it
Tval.~Type();
}
};
int main()
{
unionexample ue;
ue.print();
ue = Type(1);
ue.print();
}
输出:
ival = 0
Tval = 1
以您为例
int main()
{
Example example{ value : Final() }; // construct with Final
example.value.~Final(); // destruct Final
example.i = -1; // assign int built in type
new(&example.value) Final(); // construct
example.value.~Final(); // destruct finally
}
如果您不是出于学习目的问了这个问题,则可以像其他答案一样使用std::variant
。
谢谢。