Всем привет и доброго здравия.
Когда замерял с помощью sizeof свой класс, который хочется сжать по короче, то заметил, что с 40 байт получилось только 28 байт, переведя числовые переменные в указатели и строковые также. Булевная переменная занимает 1 байт, указатель 4 байта, перечисление тоже 4 байта.
Посчитал вручную получается 18 байтов (с учетом от базовых). А откуда 10 байтов выросли никак не пойму.
Пока пробовал сам разобраться понял, что функции и конструкторы на кол-во занимаемой памяти никак не влияют, даже static и virtual (пробовал через комментирование).
Народ, можете просветить меня в том, что упустил из внимания? Что влияет на кол-во памяти, кроме переменных хранящихся внутри класса и являющихся его членами?!
З.Ы.
Разумеется сам класс вместе с его базовыми выкладываю ниже.
Классы, которые для него базовые:
#include <QString>
enum RFGroupDataTypes {
eRFSimpleDataTypes,
eRFArea
};
class IRFDataTypes
{
public:
virtual ~IRFDataTypes() { }
virtual qint32 id() const = 0;
virtual void setId(qint32 id) = 0;
virtual QString name() const = 0;
virtual void setName(QString name) = 0;
virtual RFGroupDataTypes groupDataTypes() const = 0;
protected:
//если идентификатор равен -1, значит это либо временная переменная, либо константное значение
qint32 *_id;
//константные или временные значения имен не имеют, только переменные.
QString *_name;
//указание на принадлежность к группе типов данных.
RFGroupDataTypes _groupdatatypes;
};
//Интерфейс простых типов данных
class IRFSimpleDataTypes : public IRFDataTypes
{
public:
virtual QString valueToQString() const = 0;
protected:
//это указывает на константное значение
bool _constValue;
};
class RFSimpleDataTypes : public IRFSimpleDataTypes
{
public:
RFSimpleDataTypes()
{
_id = new qint32(-1); _name = new QString("");
_constValue = false;
_groupdatatypes = eRFSimpleDataTypes;
}
qint32 id() const {return *_id;}
void setId(qint32 id) {*_id = id;}
QString name() const {return *_name;}
void setName(QString name) {if (name != NULL) *_name = name; else *_name = "";}
RFGroupDataTypes groupDataTypes() const {return _groupdatatypes;}
bool constValue() const {return _constValue;}
void setConstValue(bool constValue) {_constValue = constValue;}
};
Сам класс:
#include <limits>
#include <cmath>
#include <time.h>
//Основа Чисел (или просто Числовой)
class RFNumeric : public RFSimpleDataTypes
{
public:
RFNumeric(double value = 0)
: RFSimpleDataTypes()
{
_isTypeInteger = false;
_value = new double;
setValue(value);
}
RFNumeric(double value, bool isTypeInteger)
: RFSimpleDataTypes()
{
setisTypeInteger(isTypeInteger);
_value = new double;
setValue(value);
}
QString valueToQString() const
{
int decpt, sign;
QString s(fcvt(*_value, 18, &decpt, &sign));
if (decpt > 0 && *_value < 0.0 ? *_value - ceil(*_value) : *_value - floor(*_value) == 0.0)
{//здесь число без цифр отличных от нуля после десятичной запятой
s.remove(decpt, s.length() - decpt);
}
else
{//наоборот
if (decpt > 0)
s = s.insert(decpt,'.');
else
{
QString s2 = "0.";
for (int i = 0; i < decpt * (-1); i++) s2 += '0';
s.insert(0, s2);
}
bool isNumberNull = true;
while(isNumberNull)
{
if (s[s.length() - 1] == '0')
{
s.remove(s.length() - 1, 1);
isNumberNull = true;
}
else
{
isNumberNull = false;
}
}
}
//после преобразования числа в строку, проверяем его на отрицательность
if (sign != 0)
s = s.insert(0, '-');
return s;
}
//целочисленное деление
static RFNumeric rfnDiv(RFNumeric a, RFNumeric b)
{
return RFNumeric(ldiv(qint32(a), qint32(b)).quot, true);
}
//% (остаток от целочисленного деления)
static RFNumeric rfnMod(RFNumeric a, RFNumeric b)
{
return RFNumeric(ldiv(qint32(a), qint32(b)).rem, true);
}
//возведение в степень
static RFNumeric rfnPow(RFNumeric a, RFNumeric b)
{
return RFNumeric(pow(double(a), double(b)), a.isTypeInteger() && b.isTypeInteger());
}
//квадратный корень
static RFNumeric rfnSqrt(RFNumeric a)
{
return RFNumeric(sqrt(double(a)), a.isTypeInteger());
}
//модуль числа
static RFNumeric rfnAbs(RFNumeric a)
{
return RFNumeric(std::abs(double(a)), a.isTypeInteger());
}
//минимальное число
static RFNumeric rfnMin(RFNumeric a, RFNumeric b)
{
double d1 = double(a), d2 = double(b);
return d1 < d2 ? RFNumeric(d1, a.isTypeInteger()) : RFNumeric(d2, b.isTypeInteger());
}
//максимальное число
static RFNumeric rfnMax(RFNumeric a, RFNumeric b)
{
double d1 = double(a), d2 = double(b);
return d1 > d2 ? RFNumeric(d1, a.isTypeInteger()) : RFNumeric(d2, b.isTypeInteger());
}
//десятичный логарифм
static RFNumeric rfnLog10(RFNumeric a)
{
return RFNumeric(log10(double(a)));
}
//натуральный логарифм
static RFNumeric rfnLog(RFNumeric a)
{
return RFNumeric(log(double(a)));
}
//экспонента в степени "a"
static RFNumeric rfnExp(RFNumeric a)
{
return RFNumeric(exp(double(a)));
}
//косинус
static RFNumeric rfnCos(RFNumeric a)
{
return RFNumeric(cos(double(a)));
}
//синус
static RFNumeric rfnSin(RFNumeric a)
{
return RFNumeric(sin(double(a)));
}
//тангенс
static RFNumeric rfnTan(RFNumeric a)
{
return RFNumeric(tan(double(a)));
}
//арктангенс
static RFNumeric rfnCtan(RFNumeric a)
{
return RFNumeric(1.0 / tan(double(a)));
}
//арккосинус
static RFNumeric rfnACos(RFNumeric a)
{
return RFNumeric(acos(double(a)));
}
//арксинус
static RFNumeric rfnASin(RFNumeric a)
{
return RFNumeric(asin(double(a)));
}
//арктангенс
static RFNumeric rfnATan(RFNumeric a)
{
return RFNumeric(atan(double(a)));
}
//арккатангенс
static RFNumeric rfnACtan(RFNumeric a)
{
return RFNumeric(1.0 / atan(double(a)));
}
//округление в сторону нуля до целого
static RFNumeric rfnFloor(RFNumeric a)
{
return RFNumeric(floor(double(a)));
}
//округление в большую сторону до целого
static RFNumeric rfnCeil(RFNumeric a)
{
return RFNumeric(ceil(double(a)));
}
//округление до целого
static RFNumeric rfnRound(RFNumeric a)
{
return RFNumeric(floor(double(a) + 0.5));
}
//выделение дробной части
static RFNumeric rfnFractional(RFNumeric a)
{
double d = double(a);
return d < 0.0 ? RFNumeric(d - ceil(d)) : RFNumeric(d - floor(d));
}
//отсечение дробной части
static RFNumeric rfnInteger(RFNumeric a)
{
double d = double(a);
return d < 0.0 ? RFNumeric(ceil(d)) : RFNumeric(floor(d));
}
//целочисленный рандом от 0 и до a-1
static RFNumeric rfnRandom(RFNumeric a)
{
srand ( time(NULL) );
return RFNumeric(rand() % qint32(a), false);
}
//рандом от 0 до 1
static RFNumeric rfnRnd()
{
srand ( time(NULL) );
return RFNumeric(double(rand() % 1001)/1000.0);
}
RFNumeric operator+(RFNumeric b)
{
return RFNumeric(this->value() + b.value(), this->isTypeInteger() && b.isTypeInteger());
}
RFNumeric operator-(RFNumeric b)
{
return RFNumeric(this->value() - b.value(), this->isTypeInteger() && b.isTypeInteger());
}
RFNumeric operator*(RFNumeric b)
{
return RFNumeric(this->value() * b.value(), this->isTypeInteger() && b.isTypeInteger());
}
RFNumeric operator/(RFNumeric b)
{
return RFNumeric(this->value() / b.value(), this->isTypeInteger() && b.isTypeInteger());
}
void operator++(int)
{
if (isTypeInteger())
*_value = checkingInt32Borders(*_value + 1);
else
*_value = checkingFloatBorders(*_value + 1);
}
void operator--(int)
{
if (isTypeInteger())
*_value = checkingInt32Borders(*_value - 1);
else
*_value = checkingFloatBorders(*_value - 1);
}
bool operator==(RFNumeric b)
{
return this->value() == double(b);
}
bool operator!=(RFNumeric b)
{
return this->value() != double(b);
}
bool operator<=(RFNumeric b)
{
return this->value() <= double(b);
}
bool operator>=(RFNumeric b)
{
return this->value() >= double(b);
}
bool operator<(RFNumeric b)
{
return this->value() < double(b);
}
bool operator>(RFNumeric b)
{
return this->value() > double(b);
}
operator QString() {return valueToQString();}
operator double() {return checkingFloatBorders(value());}
operator qint32() {return checkingInt32Borders(*_value);}
//оператор ниже позволяет передать указателю значения из экземпляра класса
operator RFNumeric*()
{
RFNumeric* prfn = new RFNumeric();
prfn->setId(id());
prfn->setConstValue(constValue());
prfn->setName(name());
prfn->setisTypeInteger(isTypeInteger());
prfn->setValue(value());
return prfn;
}
private:
long double int32Max() const {return 2147483647;}
long double int32Min() const {return -2147483647;}
long double floatMax() const {return 2.147483647e9;}
long double floatMin() const {return 2.147483647e-9;}
double checkingFloatBorders (double value) const
{
//В этой функции +/-inf приравниваются к max и min границам.
double d = fabs(value);
bool usign = value >= 0.0;
if (d >= floatMax())
return (usign) ? floatMax() : -floatMax();
if (d <= floatMin() && d > 0.0)
return (usign) ? floatMin() : -floatMin();
return value;
}
qint32 checkingInt32Borders(double value) const
{
if (value >= int32Max()) return int32Max();
if (value <= int32Min()) return int32Min();
return qint32(value);
}
void setisTypeInteger(bool isTypeInteger) {_isTypeInteger = isTypeInteger;}
//Если истинно, то значение принимается и выдается (при печати числа на экране)
// с отсечение дробной части числа и соблюдением границ типа qint32.
bool isTypeInteger() const {return _isTypeInteger;}
void setValue(double value)
{
if (isTypeInteger())
value = checkingInt32Borders(value);
else
value = checkingFloatBorders(value);
*_value = value;
}
double value() const {return checkingFloatBorders(*_value);}
double *_value;
bool _isTypeInteger;
};