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++中实现属性 本文译自http://www.codeguru.com/cpp_mfc/Property.html的Implementing a Property in C++ 以下是译文 本文由Emad Barsoum投稿。 开发测试环境:Visual C++ 7.0, Windows XP sp1, Windows 2000 sp3 摘要 本文试着在C++中不使用任何扩展技术模拟C#(或其他语言)中的属性特征。大多数在C++实现属性的库和编译器使用扩展技术,如Managed C++C++ Builder,或者他们使用如通常函数的set和get方法,但那不是属性。 详述 我们首先看一下什么是属性。一个属性表现为一个字段或者成员变量,但它通过read和write方法或者get和set方法暗中操作变量。 例如,若存在A和它的属性Count,我可以写如下的代码: A foo; Cout << foo.Count; 实际上Count调用它的get函数返回当前的变量值。你可以将属性定为只读(你可以读取它但不能修改它)、只写或者可读写,这就是使用属性而不直接使用变量的的一个最大好处了。好了,让我们开始来实现它: 我们需要能做如下的事: int i = foo.Count; //--调用get函数得到值 foo.Count = i; //-- 调用set函数设定值 因此,很明显的我们需要重载 = 操作符使其能设定变量的值,同时也要重载该属性的返回值(在下面我们将会看到的)。 我们将实现一个称为property的,它做的就像一个属性,声明如下: template class property {} 这个模板表示的是我们的属性。Container是我们要在其中包含属性变量,set和get方法以及属性型。ValueType是内部变量即要定义的属性型,nPropType定义属性的读写标志:只读、只写或可读写。 现在我们需要一个指向从包含属性Container到属性property的set和get方法的指针,同时重载 = 操作符以使得属性能象变量起那样作用。现在我们来看property的全部定义 #define READ_ONLY 1 #define WRITE_ONLY 2 #define READ_WRITE 3 template class property { public: property() { m_cObject = NULL; Set = NULL; Get = NULL; } //-- 将m_cObject指向包含属性的container -- void setContainer(Container* cObject) { m_cObject = cObject; } //-- 设定可改变属性值的set成员函数 -- void setter(void (Container::*pSet)(ValueType value)) { if((nPropType == WRITE_ONLY) || (nPropType == READ_WRITE)) Set = pSet; else Set = NULL; } //-- 设定可检索属性值的get成员函数 -- void getter(ValueType (Container::*pGet)()) { if((nPropType == READ_ONLY) || (nPropType == READ_WRITE)) Get = pGet; else Get = NULL; } //-- 重载 = 号操作符使其能用set成员设定属性值-- ValueType operator =(const ValueType& value) { assert(m_cObject != NULL); assert(Set != NULL); (m_cObject->*Set)(value); return value; } //-- 使属性能转换为内部型成为可能-- operator ValueType() { assert(m_cObject != NULL); assert(Get != NULL);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值