C++ 属性类

又一次向目标迈进了…

这次是实现一个物体所拥有的属性类。没什么好说的,非常简单。
因为我是C++新手,不知道对这次的实现有没有什么更好的实现方式。因为这个类对以后的进展很重要,而且,要充分考虑易用性,安全性,以及扩展性……
emmmmmmm…

Quality.h

#include "stdinc.h"
#include "Random.h"
#include "Rational.h"

#pragma once

namespace Lunacia 
{
	static RandomNorm g_rn(0.6, 0.15);

	/*The Quality Type. Each type corresponds to a class.*/
	enum class QualityType : uint32_t
	{
		HEALTH = 1,
		COURAGE = 2,
		ACTIVE = 4,
		INTELLIGENCE = 8,
		CREATITY = 16,
		LIFE_INSTINCT = 32
	};

	/*The base quality class.*/
	class Quality 
	{
	protected:
		/*Only class QualitiesManager can instantiate it.*/
		Quality() = delete;
		Quality(QualityType type);

		virtual ~Quality();

	public:
		Quality& operator=(const Quality&) = delete;

	public:
		void SetValue(int32_t val);
		void AddValue(int32_t inc);
		int32_t GetValue() const;

		QualityType GetType() const;

		void SetLimit(int32_t max);

		bool AddPassive(Quality*const & passive);
		bool RemovePassive(QualityType type);

		bool Cut(Quality*& otherQual);

		void Clear();
		static void Clear(Quality*& pQual);

	protected:
		virtual void PassiveImpact(const Quality*const & active) = 0;

		/*Notify all passives when the value is modified.*/
		void NotifyAll();

		void SetType(QualityType type);

	protected:
		QualityType m_type;
		Rational<int32_t> m_value;

		std::unordered_map<QualityType, Quality* const > m_passives;
	};

	typedef Quality*const & PtrQuality;
};

Quality.cpp

#include "Quality.h"

namespace Lunacia
{
	Quality::Quality(QualityType type):
		m_type(type)
	{
		m_value(0, 1000);
		m_value.SetDenomFixed(false);
	}


	Quality::~Quality()
	{
		Clear();
	}

	void Quality::SetValue(int32_t val)
	{
		int32_t& selfVal = m_value._numer;
		selfVal = val;

		if (selfVal > m_value._denom)
		{
			selfVal = m_value._denom;
		}

		if (selfVal < 0)
		{
			selfVal = 0;
		}

		NotifyAll();
	}

	void Quality::AddValue(int32_t inc)
	{
		SetValue(inc += m_value._numer);
	}

	int32_t Quality::GetValue() const
	{
		return m_value._numer;
	}

	QualityType Quality::GetType() const
	{
		return m_type;
	}

	void Quality::SetType(QualityType type)
	{
		m_type = type;
	}

	void Quality::SetLimit(int32_t max)
	{
		if (max <= 0) return;

		const float insRatio = max * 1.0f / m_value._denom;

		m_value._denom = max;
		if (m_value > 1)
		{
			m_value._numer = max;
		}
		else 
		{
			m_value._numer = static_cast<int32_t>(insRatio * m_value._numer);
		}
	}

	bool Quality::AddPassive(Quality*const & passive)
	{
		if (passive == nullptr)
		{
			return false;
		}

		return m_passives.insert(std::pair(passive->m_type, passive)).second;
	}

	bool Quality::RemovePassive(QualityType type)
	{
		return m_passives.erase(type) == 1;
	}

	bool Quality::Cut(Quality *& otherQual)
	{
		if (otherQual == nullptr || (m_type != otherQual->GetType()))
		{
			return false;
		}

		m_value = otherQual->GetValue();
		m_passives = otherQual->m_passives;

		Quality::Clear(otherQual);
		return true;
	}

	void Quality::Clear()
	{
		m_passives.clear();
		m_value = 0;
	}

	void Quality::Clear(Quality *& pQual)
	{
		if (pQual == nullptr)
		{
			return;
		}
		pQual->Clear();
		delete pQual;
		pQual = nullptr;
	}

	void Quality::NotifyAll()
	{
		for (auto& each : m_passives)
		{
			Quality* const& passive = each.second;
			if (passive != nullptr)
			{
				passive->PassiveImpact(this);
			}
		}
	}

};

QualitiesManager.h

#pragma once
#include "Quality.h"

namespace Lunacia
{
	class QualitiesManager
	{
	public:
		QualitiesManager();
		QualitiesManager(uint8_t qualMaxCount);
		~QualitiesManager();

		friend class Quality;

	public:
		void Clear();

	public:
		Quality* const& AddQuality(Quality* pQual);

		template<class T, typename  std::enable_if <std::is_base_of<Quality, T>::value, T> ::type * = nullptr >
		Quality* const& AddQuality();

		bool RemoveQuality(QualityType type);
		void RemoveAll();

		//void DestoryQuality(Quality*& pQual);

		template<class T, typename  std::enable_if <std::is_base_of<Quality, T>::value, T> ::type * = nullptr >
		Quality* const CreateQuality();

	private:
		std::unordered_map<QualityType, Quality* > m_qualities;
	};

	////////////////////////////////////////////////////////////////////////////////////////////////////
	//inline void QualitiesManager::DestoryQuality(Quality*& pQual)
	//{
	//	Quality::Clear(pQual);
	//}

	template<class T, typename  std::enable_if <
			std::is_base_of<Quality, T>::value,
		T> ::type *>
	inline Quality * const QualitiesManager::CreateQuality()
	{
		return new T();
	}

	template<class T, typename  std::enable_if <
			std::is_base_of<Quality, T>::value,
		T> ::type *>
	Quality * const& QualitiesManager::AddQuality()
	{
		return AddQuality(CreateQuality<T>());
	}
};

QualitiesManager.cpp

#include "QualitiesManager.h"


namespace Lunacia
{
	QualitiesManager::QualitiesManager()
	{
		m_qualities.reserve(10);
	}

	QualitiesManager::QualitiesManager(uint8_t qualMaxCount)
	{
		m_qualities.reserve(qualMaxCount);
	}

	QualitiesManager::~QualitiesManager()
	{
		Clear();
	}

	void QualitiesManager::Clear()
	{
		for (auto& each : m_qualities) 
		{
			Quality::Clear(each.second);
		}
		m_qualities.clear();
	}

	Quality* const& QualitiesManager::AddQuality(Quality* pQual)
	{
		//Cover add.
		QualityType type = pQual->GetType();
		if (m_qualities.find(type) != m_qualities.end())
		{
			Quality*& qual = m_qualities.at(type);
			qual->Cut(pQual);

			return qual;
		}
		auto resIt = m_qualities.insert(std::pair(type, pQual));

		return resIt.first->second;
	}

	bool QualitiesManager::RemoveQuality(QualityType type)
	{
		auto found = m_qualities.find(type);
		Quality* qualFound = (found == m_qualities.end()) ? nullptr : found->second;

		for (auto& each : m_qualities)
		{
			each.second->RemovePassive(type);
		}

		Quality::Clear(qualFound);

		return m_qualities.erase(type) == 1;
	}

	void QualitiesManager::RemoveAll()
	{
		Clear();
	}
};

*以下文件为测试用文件。

QualHealth.cpp

#include "QualHealth.h"

namespace Lunacia
{
	QualHealth::QualHealth()
		:Quality(QualityType::HEALTH)
	{

	}

	QualHealth::~QualHealth()
	{

	}

	void QualHealth::PassiveImpact(const Quality * const & active)
	{
		if (active == nullptr) return;

		int32_t val = active->GetValue();
		switch (active->GetType())
		{
		case QualityType::LIFE_INSTINCT:
			m_value._numer += static_cast<int32_t>(val * g_rn.GetRandNum<float>());	//test.
			break;

		default:
			break;
		}
		
		
	}

};

QualHealth.h

#pragma once

#include "Quality.h"

namespace Lunacia
{
	class QualHealth final : public Quality
	{
	public:
		QualHealth();
		~QualHealth();

	private:
		void PassiveImpact(const Quality*const& active);

	};
};

QualLifeInstinct.cpp

#include "QualLifeInstinct.h"

namespace Lunacia
{
	QualLifeInstinct::QualLifeInstinct()
		:Quality(QualityType::LIFE_INSTINCT)
	{
		SetValue(500);
	}

	QualLifeInstinct::~QualLifeInstinct()
	{
	}

	void QualLifeInstinct::PassiveImpact(const Quality * const & active)
	{
		//Nothing here...
		return;
	}

};

QualLifeInstinct.h

#pragma once

#include "Quality.h"
namespace Lunacia
{
	class QualLifeInstinct final : public Quality
	{
	public:
		QualLifeInstinct();
		~QualLifeInstinct();

	private:
		void PassiveImpact(const Quality*const & active);
	};

};

main.cpp

#include "Tilee.h"
#include "Location.h"
#include "stdinc.h"
#include "Random.h"
#include "Rational.h"
#include "QualitiesManager.h"
#include "QualHealth.h"
#include "QualLifeInstinct.h"

using namespace Lunacia;

struct Item 
{
	uint32_t weight;
	int id;
};

int main(void)
{
	//QualHealth
	QualitiesManager qm;
	PtrQuality ptrQualHealth = qm.AddQuality<QualHealth>();
	PtrQuality ptrQualHealth2 = qm.AddQuality<QualHealth>();

	PtrQuality ptrQualLifeIns = qm.AddQuality<QualLifeInstinct>();

	ptrQualLifeIns->AddPassive(ptrQualHealth);

	ptrQualHealth->AddValue(100);
	ptrQualHealth2->SetValue(432);

	ptrQualLifeIns->AddValue(10);

	qm.RemoveQuality(ptrQualHealth->GetType());

	RandomNorm rn(0.6, 0.15);
	for (size_t i = 0; i < 100; i++)
	{
		std::cout << rn.GetRandNum() << std::endl;
	}

	system("pause");
	return 0;
}

对于漫长的编译时间,我应该仔细考虑一下代码结构了。
下一个,物体类(object class)。

你可能感兴趣的:(C++)