又一次向目标迈进了...

这次是实现一个物体所拥有的属性类。没什么好说的,非常简单。

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

emmmmmmm................

1.潜在BUG:这种依靠加减来对属性进行回滚的方式无疑是大胆的。对于属性值为整数情况还好说,如果是小数,这势必会造成误差,而这种误差如果不修改算法难以避免。目前想到的也只有装饰器模式和状态机。使用前者,那么与现在的情况没什么两样;使用后者能够准确回滚属性值,但会造成极大的内存代价。还没有什么好的解决方式我能想起来的。但,被修改是迟早的事情。(2018.10.30 17:01)

2.BUGFIX:

2.1 增加了Get函数。(2018.11.1 19:20)

Quality.h

#pragma once

#include "stdinc.h"
#include "Rational.h" #include "QualDefine.h" namespace Lunacia
{
/*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, bool isForce = false);
void AddValue(int32_t inc);
int32_t GetValue() const; QualityType GetType() const; void SetLimit(int32_t max);
int32_t GetLimit(); bool AddPassive(Quality*const & passive);
bool RemovePassive(QualityType type);
bool RebackPassiveValue(QualityType type);
void RebackAllPassiveValue(); bool Cut(Quality*& otherQual); virtual void Clear();
static void Clear(Quality*& pQual); protected:
virtual Rational<int32_t> 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;
std::unordered_map<QualityType, Rational<int32_t>> m_passivesValue;
}; 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, bool isForce)
{
int32_t& selfVal = m_value._numer;
selfVal = val; if (selfVal > m_value._denom)
{
selfVal = m_value._denom;
} if (selfVal < 0)
{
selfVal = 0;
} if(!isForce) NotifyAll();
} void Quality::AddValue(int32_t inc)
{
SetValue(inc += m_value._numer, false);
} 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);
}
} int32_t Quality::GetLimit()
{
return m_value._denom;
} bool Quality::AddPassive(Quality*const & passive)
{
if (passive == nullptr)
{
return false;
} bool res2 = m_passives.insert(std::pair(passive->m_type, passive)).second; Rational<int32_t> pv(0, 0);
bool res1 = m_passivesValue.insert(std::pair(passive->m_type, pv)).second; return res2;
} bool Quality::RemovePassive(QualityType type)
{
RebackPassiveValue(type); m_passivesValue.erase(type);
return m_passives.erase(type) == 1;
} bool Quality::RebackPassiveValue(QualityType type)
{
auto itFound_pv = m_passivesValue.find(type);
auto itFound = m_passives.find(type); if (itFound_pv == m_passivesValue.end() ||
itFound == m_passives.end())
{
return false;
} Rational<int32_t>& pvVal = itFound_pv->second;
itFound->second->SetLimit(itFound->second->m_value._denom -= pvVal._denom);
itFound->second->AddValue(pvVal._numer * -1); pvVal(0, 0);
return true;
} void Quality::RebackAllPassiveValue()
{
for (auto itEach : m_passives)
{
RebackPassiveValue(itEach.second->GetType());
}
} bool Quality::Cut(Quality *& otherQual)
{
if (otherQual == nullptr || (m_type != otherQual->GetType()))
{
return false;
} m_value = otherQual->GetValue();
m_passives = otherQual->m_passives;
m_passivesValue = otherQual->m_passivesValue; Quality::Clear(otherQual);
return true;
} void Quality::Clear()
{
m_passives.clear();
m_passivesValue.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)
{
Rational<int32_t> pv = passive->PassiveImpact(this);
if (pv._denom != 0 || pv._numer != 0)
{
Rational<int32_t>& pvEach = m_passivesValue[each.first];
pvEach._denom += pv._denom;
pvEach._numer += pv._numer;
}
}
}
} };

QualitiesManager.h

#pragma once
#include "Quality.h" namespace Lunacia
{
class QualitiesManager
{
#ifdef __Debug
public:
#else
private:
#endif // __Debug
QualitiesManager();
QualitiesManager(uint8_t qualInitCount);
~QualitiesManager(); static QualitiesManager* CreateQualManager(uint8_t qualInitCount = 10);
static void DestoryQualManager(QualitiesManager* pQualManager); public:
friend class LunaObject; void Clear(); public:
Quality* const& AddQuality(Quality* pQual, bool isCover = false); 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(); const Quality* const GetQuality(QualityType type) const;
Quality* const FindQuality(QualityType type); 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 qualInitCount)
{
m_qualities.reserve(qualInitCount);
} QualitiesManager::~QualitiesManager()
{
Clear();
} QualitiesManager * QualitiesManager::CreateQualManager(uint8_t qualInitCount)
{
return new QualitiesManager(qualInitCount);
} void QualitiesManager::DestoryQualManager(QualitiesManager * pQualManager)
{
pQualManager->Clear(); delete pQualManager;
pQualManager = nullptr;
} void QualitiesManager::Clear()
{
for (auto& each : m_qualities)
{
Quality::Clear(each.second);
}
m_qualities.clear();
} Quality* const& QualitiesManager::AddQuality(Quality* pQual, bool isCover)
{
QualityType type = pQual->GetType();
auto itFound = m_qualities.find(type); if (itFound != m_qualities.end())
{
Quality* &qual = itFound->second;
if (isCover)
qual->Cut(pQual);
else
qual->AddValue(pQual->GetValue()); return qual;
} return m_qualities.insert(std::pair(type, pQual)).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();
} const Quality * const QualitiesManager::GetQuality(QualityType type) const
{
auto itFound = m_qualities.find(type);
if (itFound == m_qualities.end())
{
return nullptr;
}
return itFound->second;
} Quality * const QualitiesManager::FindQuality(QualityType type)
{
Quality * const res = const_cast<Quality * const>(GetQuality(type));
return res;
}
};

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

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++ 属性类的更多相关文章

  1. java中dao层的通用层,通过反射机制,操作数据库的增删改,适用的范围是不包含属性类

    这里首先必须注意的是:类的类名.字段必须与数据库中的表名和字段名保持一致,否则无法通过反射机制作出通用层 /** * 学生信息类,数据库中的StuInfo表 * */public class StuI ...

  2. springboot属性类自动加载配置文件中的值

    springboot属性类自动加载配置文件中的值,如Person类加载在yml中配置的name,age等属性值,可以通过如下步骤获取: 类上添加@ConfigurationProperties注解,p ...

  3. Swift-存储属性,计算属性,类属性

    //类的属性定义 class Student: NSObject { // 定义属性 // 定义存储属性 var age : Int = var name :String? var mathScore ...

  4. PHP面向对象学习-属性 类常量 类的自动加载 构造函数和析构函数 访问控制(可见性)

    在类的成员方法里面,可以用 ->(对象运算符):$this->property(其中 property 是该属性名)这种方式来访问非静态属性.静态属性则是用 ::(双冒号):self::$ ...

  5. .NET Framework的属性类对控件的支持功能

     ToolBoxItem 此属性为类特性.属于工具箱属性,可以设置当前控件是否在工具箱中显示,以及所在工具箱项的类型名称等信息.默认生成的控件都显示在工具箱中. 更多设计时属性介绍: 4.3 属性的 ...

  6. 属性类:Properties

    属性是程序中经常出现的形式. 在类集中提供了一种专门的Properties类. public class Propertiesextends Hashtable<Object,Object> ...

  7. NSAttributedString字符串属性类

    //定义一个可变字符串属性对象aStr NSMutableAttributedString *aStr = [[NSMutableAttributedString alloc]initWithStri ...

  8. VB6 仿.netWinfrom控件 Anchor属性类

    vb6中控件没有anchor与dock属性,窗体变大后原来要在resize中调整控件的move属性,否则就面目全非了.网上找到一些调整控件大小的代码,发现并不太适合自己,于是按照思路自己做了一个类似a ...

  9. 静态方法块 static 以及对象属性&类属性的用法

    使用静态块的好处:只要在类被加载时,static块就会被调用,整个过程就调用这么一次,不会在后面的对象处又不断的调用.如果不使用它,就会出现如下问题:new一个对象,我就要调用一次所需的这些内容,重复 ...

随机推荐

  1. 动态规划———最长公共子序列(LCS)

    最长公共子序列+sdutoj2080改编: http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Contest/contestproblem/cid/ ...

  2. python异常(概念、捕获、传递、抛出)

    异常 目标 异常的概念 捕获异常 异常的传递 抛出异常 01. 异常的概念 程序在运行时,如果 Python 解释器 遇到 到一个错误,会停止程序的执行,并且提示一些错误信息,这就是 异常 程序停止执 ...

  3. 使用SQL语句操作数据

    一.SQL 结构化查询语言 1.T-SQL 和 SQL的关系 T-SQL是SQL的增强版 2.SQL的组成 2.1 DML (数据操作语言) 增加,修改,删除等数据操作 2.2 DCL (数据控制语言 ...

  4. L342 Air Pollution Is Doing More Than Just Slowly Killing Us

    Air Pollution Is Doing More Than Just Slowly Killing Us In the future, the authorities might need to ...

  5. 马凯军201771010116《面向对象与程序设计Java》第十三周学习总结

    实验十三  图形界面事件处理技术 实验时间 2018-11-22 理论知识与学习部分 事件处理基础  事件源(event source):能够产生事件的对象都可 以成为事件源,如文本框.按钮等.一个事 ...

  6. CenOS 更换yum源

    说明: 更换CentOS yum源既是修改配置文件/etc/yum.repos.d/CentOS-Base.repo. 目前有很多公司都提供yum源文件的下载,所以我们可以不需要去修改这个文件,直接从 ...

  7. VS2010 配置与调试

    一.VS2010项目属性配置 使用VS调试程序,出现错误:"无法启动程序"***\**.exe".系统找不到指定的文件".网上找来解决办法, 也未能解决,但这些 ...

  8. JAVA8集合之List

    目录: 一.ArrayList概述 二.ArrayList的实现 1)成员变量 2)构造方法 3)元素添加 4)元素删除 5)元素修改 6)集合容量调整 7)集合转数组 三.总结 一.ArrayLis ...

  9. springboot+ibatis 多数据源配置

    这个是boot基本版本包,因为我用的打包方式是war所以去除掉了boot内置的tomcat,但是为了方便测试又引入了内置tomcat,只要添加<scope>provided</sco ...

  10. nginx 配置 同一域名端口下,根据URL 导向不同的项目目录

    我们现在拥有2个项目.但是只有一个域名,通过nginx配置来实现以下url导向不同的项目. 后台管理台:{域名}/admin 用户客户端:{域名}/client server { listen 888 ...