我是一个老C-dude,试图通过将我的旧状态机框架从C移植到C++11来学习C++11,我的想法是为状态机本身创建一个类,然后为其中的状态创建嵌套类。状态可以是分层的,即超状态和子状态。框架需要知道状态的超状态,为此,我在嵌套的状态类中有一个指针(state *superstate)。
我的问题是,我打算通过在机器的类中直接使用构造函数来设置超级状态指针,这在使用非静态数据成员初始化的C++11中应该是可能的,通过使用统一初始化。但是由于某些原因,当它被设置为另一种类型的状态/类时,它无法编译(substateB3{superstateA})。但是,如果我稍后使用一个特定的函数(set_superstate)来设置它,它就可以很好地工作,该函数具有与构造函数相同的参数!有趣的是,如果我将superstate设置为相同类型的状态/类(substateB2{substateB1}),则构造函数会被接受。
我使用的是gcc 4.7.0 (为了获得对非静态数据成员初始值设定项的支持),下面是我的代码:
// My state-machine framework (simplified)
struct machine {
struct state {
state() : superstate(nullptr) { } // No superstate => toplevel state!
state(state &superstate) : superstate(&superstate) { }
state *superstate;
void set_superstate(state &superstate) { this->superstate = &superstate; } // Non-ctor way to set superstate
};
};
// An example of a specific state-machine using my framework
struct Machine : machine {
struct SuperstateA : state {
} superstateA;
struct SubstateB : state {
} substateB1, // Compiles OK; gets its superstate set in Machine's ctor below
substateB2{substateB1}, // Compiles OK; but not correct superstate
substateB3{superstateA}; // gcc 4.7.0 error: could not convert ‘{((Machine*)this)->Machine::superstateA}’ from ‘<brace-enclosed initializer list>’ to ‘Machine::SubstateB’
Machine() { substateB1.set_superstate(superstateA); } // Compiles OK;
} myMachine;非常感谢您的任何建议或指导!:)
发布于 2012-05-21 07:04:45
剥离一层继承:
struct m {
struct state { state *s;
state() : s(0) {};
state(state &s) : s(&s) {}
set(state &s) { this->s = &s; }
};
struct s1 : state {} A; // calls s1(), the default constructor
struct s2 : state {} B // calls s2(), ditto
, C{B} // calls s2(const s2&), the default copy constructor
, D{A}; // calls s2(const s1&)
m() { B.set(A); } // The m() body runs after all the members are constructed.
} M;你会得到构造错误,因为你的子状态没有声明构造函数,所以它们得到了编译器提供的默认值,并且没有来自兄弟类或基类的引用(编译器不提供s2(s1&)或s2(state&))。
您得到了错误的C超级状态,因为C{B}调用了默认的复制构造函数s2(s2&),该函数在m()的正文之前运行。
下面是你想要的:
struct m {
struct state { state *s; state() : s(0) {} state(state &s) : s(&s) {} };
struct s1 : state {} A; // default-constructs, fine
struct s2 : state {
s2(state &s) : state(s) {}
s2(s2&s) : state(s) {}
} B // default-constructs
, C{B} // calls s2(s2&), invokes state(state&)
, D{A}; // calls s2(state&)
;
m() : B(A) {};
} M;当M的构造函数运行时,首先是它的基类(没有),然后是使用指定的初始化以声明顺序构造它的成员。只有一个:B(A),所以所有其他的都是默认的。在构造完所有的基础和成员之后,对象构造函数的主体就会运行。
发布于 2012-05-21 06:39:23
struct SuperstateA : state {
} superstateA;
struct SubstateB : state {
} substateB1,
substateB3{superstateA};SuperstateA和SubstateB之间没有允许在它们之间进行转换或切片的关系。即使SuperstateA是一个基类(通常与“超级”相关联),SubstateB仍然会有更多的成员(作为子类),并且不可能从不同类型的对象全部初始化它们。
这不是编译器中的错误,也不是C++的任意限制。执行这种初始化是不可能的。需要有一种"is-a“的关系。
另一方面,superstateA和substateB1都可以转换为state & (或者它们的指针可以转换为state *),因此提供SubstateB::SubstateB( state & )可以很好地修补所有漏洞。
https://stackoverflow.com/questions/10677237
复制相似问题