IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++编译错误:多个类定义与使用的顺序问题 -> 正文阅读

[C++知识库]C++编译错误:多个类定义与使用的顺序问题

项目场景:

在使用C++实现状态模式的例子时,发现出现编译错误,一开始以为是使用了未定义的类导致的,添加了类的声明后发现还是编译失败,很伤心。

问题描述:

首先上图:
在这里插入图片描述
然后是源码:

#include <iostream>
#include <memory>

//*********************State Pattern*******************
class Work;

//抽象状态类
class State
{
public:
	virtual void WriteProgram(Work* ptrWork) = 0;
};

class ForenoonState;

//工作类
class Work
{
private:
	std::shared_ptr<State> smartState;
	double hour;
	bool finish;

public:
	//Work();
	Work() : hour(0), finish(false), smartState(std::make_shared<ForenoonState>()) {}

	void SetHour(const double h)
	{
		hour = h;
	}

	double GetHour() const
	{
		return hour;
	}

	void SetFinish(bool bFinish)
	{
		finish = bFinish;
	}

	bool GetFinish() const
	{
		return finish;
	}

	void SetState(std::shared_ptr<State> pState)
	{
		smartState = pState;
	}

	std::shared_ptr<State> GetState() const
	{
		return smartState;
	}

	void WriteProgram()
	{
		smartState->WriteProgram(this);
	}

};

//睡眠状态
class SleepingState : public State
{
public:
	void WriteProgram(Work* ptrWork)
	{
		std::cout << "当前时间:" << ptrWork->GetHour() << "点 撑不住了,睡觉吧!" << std::endl;
	}
};

//下班休息状态
class RestState : public State
{
public:
	void WriteProgram(Work* ptrWork)
	{
		std::cout << "当前时间:" << ptrWork->GetHour() << "点 下班回家了!" << std::endl;
	}
};

//傍晚工作状态
class EveningState : public State
{
public:
	void WriteProgram(Work* ptrWork)
	{
		if (ptrWork->GetFinish())
		{
			ptrWork->SetState(std::make_shared<RestState>());
			ptrWork->WriteProgram();
			return;
		}

		if (ptrWork->GetHour() < 21)
		{
			std::cout << "当前时间:" << ptrWork->GetHour() << "点 加班吆,疲惫啊!" << std::endl;
		}
		else
		{//超过21点,转换到睡眠状态
			ptrWork->SetState(std::make_shared<SleepingState>());
			ptrWork->WriteProgram();
		}
	}
};

//下午工作状态
class AfternoonState : public State
{
public:
	void WriteProgram(Work* ptrWork)
	{
		if (ptrWork->GetHour() < 17)
		{
			std::cout << "当前时间:" << ptrWork->GetHour() << "点 下午状态还不错,继续努力!" << std::endl;
		}
		else
		{//超过17点,转换傍晚工作状态
			ptrWork->SetState(std::make_shared<EveningState>());
			ptrWork->WriteProgram();
		}
	}
};

//中午工作状态
class NoonState : public State
{
public:
	void WriteProgram(Work* ptrWork)
	{
		if (ptrWork->GetHour() < 13)
		{
			std::cout << "当前时间:" << ptrWork->GetHour() << "点 饿了,午饭,犯困,午休!" << std::endl;
		}
		else
		{//超过13点,转换下午工作状态
			ptrWork->SetState(std::make_shared<AfternoonState>());
			ptrWork->WriteProgram();
		}
	}
};

//上午工作状态类
class ForenoonState : public State
{
public:
	void WriteProgram(Work* ptrWork)
	{
		if (ptrWork->GetHour() < 12)
		{
			std::cout << "当前时间:" << ptrWork->GetHour() << "点 上午工作,精神百倍!" << std::endl;
		}
		else
		{//超过12点,转换中午工作状态
			ptrWork->SetState(std::make_shared<NoonState>());
			ptrWork->WriteProgram();
		}
	}
};

//Work::Work() : hour(0), finish(false), smartState(std::make_shared<ForenoonState>()) {}


//************************Test**************************
int main()
{
	std::shared_ptr<Work> work = std::make_shared<Work>();
	
	work->SetHour(9);
	work->WriteProgram();

	work->SetHour(10);
	work->WriteProgram();

	work->SetHour(12);
	work->WriteProgram();

	work->SetHour(13);
	work->WriteProgram();

	work->SetHour(14);
	work->WriteProgram();

	work->SetHour(17);
	work->WriteProgram();

	work->SetFinish(false);
	//work->SetFinish(true);
	//work->WriteProgram();

	work->SetHour(19);
	work->WriteProgram();

	work->SetHour(22);
	work->WriteProgram();

	system("pause");
	return 0;
}

原因分析:

从错误信息看,应该是将std::shared_ptr转换为std::shared_ptr失败导致的,但是很奇怪,类ForenoonState是State类的子类,子类转换为父类有什么问题?看了ForenoonState类的声明与定义发现,之前为了能够在Work类中使用ForenoonState类,将ForenoonState类的声明放在Work类的定义前,但是只有在类的定义中才有继承关系,但是由于ForenoonState类的依赖关系,必须把它的定义放在Work类的后面。


解决方案:

这该怎么办呢?头疼了半天,在网上也没有搜到相应的结果,关键是不好描述这个问题。但是呢,灵机一动,突然想到,可以先将类的完整信息声明出来啊,比如有哪些属性,有哪些函数接口,具体实现可以放到后面来做。对于上述问题,不就是将Work类的构造函数先声明,然后在ForenoonState类的定义后面实现Work类的构造函数不久可以了,想到就做到。

Work类构造函数声明更改:

//工作类
class Work
{
private:
	...

public:
	Work();//更改后
	//Work() : hour(0), finish(false), smartState(std::make_shared<ForenoonState>()) {}//更改前

Work类构造函数定义实现:

//上午工作状态类
class ForenoonState : public State
{
	...
};

Work::Work() : hour(0), finish(false), smartState(std::make_shared<ForenoonState>()) {}

注意要将Work类构造函数放在ForenoonState类定义的后面。

问题解决!编译成功,运行OK, Nice!!!

看来,仅仅声明子类,当将子类转换为父类对象时,编译器是无法知道子类与父类间的继承关系的,之前都没有注意到!!!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-07 10:38:51  更:2021-09-07 10:40:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:26:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码