今天学习状态模式的时候出现了一个编译问题,提示错误:没有合适的默认构造函数。一开始是怀疑是类之间内部引用的问题,所以在文件顶部把所有的定义的类都声明了一遍,发现还是不行,就到网上了解了一下得到这么一个说法,‘超前引用’。
所谓超前引用是指一个类型在定义之前就被用来定义变量和声明函数。
下面看我的代码:
#include <iostream>
using namespace std;
class Context;//声明
class ConcreteStateB;
class ConcreteStateC;
//抽象出来的状态类
class State
{
public:
virtual void Handle(Context *context) = 0;
};
//状态管理类
class Context
{
public:
//初始化状态
Context(State *state)
{
m_pState = state;
}
//执行状态类实现的方法
void Request()
{
m_pState->Handle(this);
}
State* m_pState;
};
//具体的状态子类
class ConcreteStateA:public State
{
public:
void Handle(Context *context)
{
context->m_pState = new ConcreteStateB;
}
};
//具体的状态子类
class ConcreteStateB:public State
{
public:
void Handle(Context *context)
{
context->m_pState = new ConcreteStateC;
}
};
//具体的状态子类
class ConcreteStateC:public State
{
public:
void Handle(Context *context)
{
context->m_pState = new ConcreteStateA;
}
};
为了方便我把类和成员函数的定义和声明都写在了.h文件中,很明显犯了超前引用的错误类型定义之前就被用来定义变量和声明函数。
为什么会出现超前引用错误呢?我已经在前边声明了需要用到的类。其实原因是这样的,编译器编译的时候,看到我们声明的类实际上是空的,里边什么也没有。当然也没有默认的构造析构函数了,所以编译器在用到构造的时候就会提示找不到构造函数了。
修改很简单,把函数的定义放在类之后或者cpp文件就行了。
就像这样:
#include <iostream>
using namespace std;
class Context;//声明
//抽象出来的状态类
class State
{
public:
virtual void Handle(Context *context) = 0;
};
//状态管理类
class Context
{
public:
//初始化状态
Context(State *state)
{
m_pState = state;
}
//执行状态类实现的方法
void Request()
{
m_pState->Handle(this);
}
State* m_pState;
};
//具体的状态子类
class ConcreteStateA:public State
{
public:
void Handle(Context *context);
};
//具体的状态子类
class ConcreteStateB:public State
{
public:
void Handle(Context *context);
};
//具体的状态子类
class ConcreteStateC:public State
{
public:
void Handle(Context *context)
{
context->m_pState = new ConcreteStateA;
}
};
//子类中函数的实现放在后边,前边提前的对B和C两个子类的声明也可以去掉了。
void ConcreteStateA:: Handle(Context *context)
{
context->m_pState = new ConcreteStateB;
}
void ConcreteStateB:: Handle(Context *context)
{
context->m_pState = new ConcreteStateC;
}
编译通过了,注意不要有cpp文件。