C++ 属性类
又一次向目标迈进了...
这次是实现一个物体所拥有的属性类。没什么好说的,非常简单。
因为我是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++ 属性类的更多相关文章
- java中dao层的通用层,通过反射机制,操作数据库的增删改,适用的范围是不包含属性类
这里首先必须注意的是:类的类名.字段必须与数据库中的表名和字段名保持一致,否则无法通过反射机制作出通用层 /** * 学生信息类,数据库中的StuInfo表 * */public class StuI ...
- springboot属性类自动加载配置文件中的值
springboot属性类自动加载配置文件中的值,如Person类加载在yml中配置的name,age等属性值,可以通过如下步骤获取: 类上添加@ConfigurationProperties注解,p ...
- Swift-存储属性,计算属性,类属性
//类的属性定义 class Student: NSObject { // 定义属性 // 定义存储属性 var age : Int = var name :String? var mathScore ...
- PHP面向对象学习-属性 类常量 类的自动加载 构造函数和析构函数 访问控制(可见性)
在类的成员方法里面,可以用 ->(对象运算符):$this->property(其中 property 是该属性名)这种方式来访问非静态属性.静态属性则是用 ::(双冒号):self::$ ...
- .NET Framework的属性类对控件的支持功能
ToolBoxItem 此属性为类特性.属于工具箱属性,可以设置当前控件是否在工具箱中显示,以及所在工具箱项的类型名称等信息.默认生成的控件都显示在工具箱中. 更多设计时属性介绍: 4.3 属性的 ...
- 属性类:Properties
属性是程序中经常出现的形式. 在类集中提供了一种专门的Properties类. public class Propertiesextends Hashtable<Object,Object> ...
- NSAttributedString字符串属性类
//定义一个可变字符串属性对象aStr NSMutableAttributedString *aStr = [[NSMutableAttributedString alloc]initWithStri ...
- VB6 仿.netWinfrom控件 Anchor属性类
vb6中控件没有anchor与dock属性,窗体变大后原来要在resize中调整控件的move属性,否则就面目全非了.网上找到一些调整控件大小的代码,发现并不太适合自己,于是按照思路自己做了一个类似a ...
- 静态方法块 static 以及对象属性&类属性的用法
使用静态块的好处:只要在类被加载时,static块就会被调用,整个过程就调用这么一次,不会在后面的对象处又不断的调用.如果不使用它,就会出现如下问题:new一个对象,我就要调用一次所需的这些内容,重复 ...
随机推荐
- 如何用jmeter进行数据库性能测试
由于业务需要,需要进行数据库性能测试,记录过程进行学习 测试前期准备: 1.测试点准备及需求点 a.性能测试目的 b.jmeter测试数据库基本脚本 get c.数据库性能监控工具选择 d.服务器性 ...
- Ganlia采样、统计及RRD记录周期(频次、间隔)的配置和更改
Ganglia & RRD Ganglia是伯克利开发的一个集群监控软件.可以监视和显示集群中的节点的各种状态信息,比如如:cpu .mem.硬盘利用率, I/O负载.网络流量情况等,同时可以 ...
- app模块设计
至于app模块设计,要坚持三个原则: 1.放羊,让用户决定模块间的组合与穿插. 2.滥竽充数,对于用户不希望的模块,可以悄悄植入以实现产品目标. 3.照葫芦画瓢,遵守用户在其它APP上的既有习惯,组合 ...
- 信息技术手册可视化进度报告 基于jieba的关键字提取技术
在这一篇博客之前,我已经将word文件中的内容通过爬虫的方式整理到数据库中了,但是为了前台展示的需要,还必须提取出关键字,用于检索. 我用的是jieba分词,GitHub地址:https://gith ...
- python网络编程(UDP+广播)
UDP广播案例,一端发送,多端接受: 发送端: # UDP广播案例 from socket import * from time import sleep # 设定目标地址 dest=('176.21 ...
- Python成长之路【第三篇】函数
函数 一.背景 在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处 ...
- like 内容转义
如题,当SQL语句中使用Like查询,且期望匹配的结果中含有"\"的,应当把"\"替换为"\\\\". 比如数据库中text字段有以下三行: ...
- JavaScript的popup框
JavaScript中可以创建三种消息框:警告框.确认框.提示框. 1.警告框 警告框经常用于确保用户可以得到某些信息. 当警告框出现后,用户需要点击确定按钮才能继续进行操作. 语法:alert(&q ...
- Mybatis-基于配置文件的配置(——纪念这个即将被抛弃的孩子)
虽然内心相信Mybatis基于配置文件的配置早已经在实战之中被注解所遗忘,但是我相信还是会有一小部分人还是需要这种技术去维护原有使用这种方式去搭建的项目. 废话不多说首先使用框架包是不能少的了.导入M ...
- BUAAOO P1-P3 Expression Dirivation
目录 1.问题描述 1.1.概念定义 7.程序度量 8.知识点笔记 1.运行 2.1.方法 2.2.检测相等性 2.3.空串与null串 2.4.使用StringBuilder构建字符串 2.5.使用 ...