Russian Qt Forum
Ноябрь 23, 2024, 21:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Полиморфизм, наследование, проверка на принадлежность к группе классов.  (Прочитано 9842 раз)
Eten
Гость
« : Март 27, 2011, 10:06 »

Я разобрался с полиморфизмом и наследованием. И на данный момент я перешел на использование интерфейсов, вместо старого базового класса. Т.е. у меня все хранится в базовом интерфейсе (естественно через указатели), а не в базовом классе, т.к. по сути он в себе хранит переданный ему класс (по адресу указателя видно). И по смыслу интерфейсами лучше. Т.е. способ работы от этого не изменился.

typeid по конечному классу (NNumeric, NString, NLogical)  у меня нормально проверяет, а вот попытки проверить на базовый класс NSimpleDataTypes (т.е. попытка проверки конечного класса на принадлежность к NSimpleDataTypes, как к группе) не увенчиваются успехом. Когда все проверил и еще раз перечитал нужную литературу понял, что typeid подходит только чисто для проверки класса на тип. Т.е. типы от которых он наследовался я проверить не смогу.

В общем, что нужно и как правильно задать что-то, чтобы можно было создать проверку класса на принадлежность к группе классов? Например, NNumeric принадлежит к группе NSimpleDataTypes, т.к. является производным от этого класса. Заранее скажу, что я понимаю и помню о возможности нагрузить классы доп. полями для реализации подобного, но хочу узнать от толковых людей, есть ли возможность достичь желаемого результата не замусоривая т.о. классы.


Интерфейсы:
Код
C++ (Qt)
class INDataTypes
{
public:
   virtual ~INDataTypes() { }
   virtual qint32 id() const = 0;
   virtual void setId(qint32 id) = 0;
   virtual QString name() const = 0;
   virtual void setName(QString name) = 0;
 
protected:
   //если идентификатор равен -1, значит это либо временная переменная, либо константное значение
   qint32 _id;
   //константные или временные значения имен не имеют, только переменные.
   QString _name;
};
 
 
class INSimpleDataTypes : public INDataTypes
{
public:
   virtual QString valueToQString() const = 0;
 
protected:
   //это указывает на константное значение
   bool _constValue;
};
 


Базовый класс:
Код
C++ (Qt)
   class NSimpleDataTypes : public INSimpleDataTypes
   {
   public:
       NSimpleDataTypes() {_id = -1; _name = ""; _constValue = false;}
 
       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 = "";}
 
       bool constValue() const {return _constValue;}
       void setConstValue(bool constValue) {_constValue = constValue;}
   };
 


Производный от него класс NNumeric:
Код
C++ (Qt)
class NNumeric : public NSimpleDataTypes
{
public:
 
   NNumeric(double value = 0)
       : NSimpleDataTypes()
   {
       _isTypeInteger = false;
       setValue(value);
   }
 
   NNumeric(double value, bool isTypeInteger)
           : NSimpleDataTypes()
   {
       setisTypeInteger(isTypeInteger);
       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 NNumeric nnDiv(NNumeric a, NNumeric b)
   {
       return NNumeric(ldiv(qint32(a), qint32(b)).quot, true);
   }
 
   //% (остаток от целочисленного деления)
   static NNumeric nnMod(NNumeric a, NNumeric b)
   {
       return NNumeric(ldiv(qint32(a), qint32(b)).rem, true);
   }
 
   //возведение в степень
   static NNumeric nnPow(NNumeric a, NNumeric b)
   {
       return NNumeric(pow(double(a), double(b)), a.isTypeInteger() && b.isTypeInteger());
   }
 
   //квадратный корень
   static NNumeric nnSqrt(NNumeric a)
   {
       return NNumeric(sqrt(double(a)), a.isTypeInteger());
   }
 
   //модуль числа
   static NNumeric nnAbs(NNumeric a)
   {
       return NNumeric(std::abs(double(a)), a.isTypeInteger());
   }
 
   //минимальное число
   static NNumeric nnMin(NNumeric a, NNumeric b)
   {
       double d1 = double(a), d2 = double(b);
       return d1 < d2 ? NNumeric(d1, a.isTypeInteger()) : NNumeric(d2, b.isTypeInteger());
   }
 
   //максимальное число
   static NNumeric nnMax(NNumeric a, NNumeric b)
   {
       double d1 = double(a), d2 = double(b);
       return d1 > d2 ? NNumeric(d1, a.isTypeInteger()) : NNumeric(d2, b.isTypeInteger());
   }
 
   //десятичный логарифм
   static NNumeric nnLog10(NNumeric a)
   {
       return NNumeric(log10(double(a)));
   }
 
   //натуральный логарифм
   static NNumeric nnLog(NNumeric a)
   {
       return NNumeric(log(double(a)));
   }
 
   //экспонента в степени "a"
   static NNumeric nnExp(NNumeric a)
   {
       return NNumeric(exp(double(a)));
   }
 
   //косинус
   static NNumeric nnCos(NNumeric a)
   {
       return NNumeric(cos(double(a)));
   }
 
   //синус
   static NNumeric nnSin(NNumeric a)
   {
       return NNumeric(sin(double(a)));
   }
 
   //тангенс
   static NNumeric nnTan(NNumeric a)
   {
       return NNumeric(tan(double(a)));
   }
 
   //арктангенс
   static NNumeric nnCtan(NNumeric a)
   {
       return NNumeric(1.0 / tan(double(a)));
   }
 
   //арккосинус
   static NNumeric nnACos(NNumeric a)
   {
       return NNumeric(acos(double(a)));
   }
 
   //арксинус
   static NNumeric nnASin(NNumeric a)
   {
       return NNumeric(asin(double(a)));
   }
 
   //арктангенс
   static NNumeric nnATan(NNumeric a)
   {
       return NNumeric(atan(double(a)));
   }
 
   //арккатангенс
   static NNumeric nnACtan(NNumeric a)
   {
       return NNumeric(1.0 / atan(double(a)));
   }
 
   //округление в сторону нуля до целого
   static NNumeric nnFloor(NNumeric a)
   {
       return NNumeric(floor(double(a)));
   }
 
   //округление в большую сторону до целого
   static NNumeric nnCeil(NNumeric a)
   {
       return NNumeric(ceil(double(a)));
   }
 
   //округление до целого
   static NNumeric nnRound(NNumeric a)
   {
       return NNumeric(floor(double(a) + 0.5));
   }
 
   //выделение дробной части
   static NNumeric nnFractional(NNumeric a)
   {
       double d = double(a);
       return d < 0.0 ? NNumeric(d - ceil(d)) : NNumeric(d - floor(d));
   }
 
   //отсечение дробной части
   static NNumeric nnInteger(NNumeric a)
   {
       double d = double(a);
       return d < 0.0 ? NNumeric(ceil(d)) : NNumeric(floor(d));
   }
 
   //целочисленный рандом от 0 и до a-1
   static NNumeric nnRandom(NNumeric a)
   {
       srand ( time(NULL) );
       return NNumeric(rand() % qint32(a), false);
   }
 
   //рандом от 0 до 1
   static NNumeric nnRnd()
   {
       srand ( time(NULL) );
       return NNumeric(double(rand() % 1001)/1000.0);
   }
 
 
   NNumeric operator+(NNumeric b)
   {
       return NNumeric(this->value() + b.value(), this->isTypeInteger() && b.isTypeInteger());
   }
 
   NNumeric operator-(NNumeric b)
   {
       return NNumeric(this->value() - b.value(), this->isTypeInteger() && b.isTypeInteger());
   }
 
   NNumeric operator*(NNumeric b)
   {
       return NNumeric(this->value() * b.value(), this->isTypeInteger() && b.isTypeInteger());
   }
 
   NNumeric operator/(NNumeric b)
   {
       return NNumeric(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==(NNumeric b)
   {
       return this->value() == double(b);
   }
 
   bool operator!=(NNumeric b)
   {
       return this->value() != double(b);
   }
 
   bool operator<=(NNumeric b)
   {
       return this->value() <= double(b);
   }
 
   bool operator>=(NNumeric b)
   {
       return this->value() >= double(b);
   }
 
   bool operator<(NNumeric b)
   {
       return this->value() < double(b);
   }
 
   bool operator>(NNumeric b)
   {
       return this->value() > double(b);
   }
 
   operator QString() {return valueToQString();}
 
   operator double() {return checkingFloatBorders(value());}
 
   operator qint32() {return checkingInt32Borders(_value);}
 
   //оператор ниже позволяет передать указателю значения из экземпляра класса
   operator NNumeric*()
   {
       NNumeric* pnn = new NNumeric();
 
       pnn->setId(id());
       pnn->setConstValue(constValue());
       pnn->setName(name());
       pnn->setisTypeInteger(isTypeInteger());
       pnn->setValue(value());
 
       return pnn;
   }
 
 
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;
};
 
Записан
Eten
Гость
« Ответ #1 : Март 27, 2011, 11:25 »

В общем, ничего такого не нашел. Поэтому сделал, с помощью перечисления. Все работает.

Интерфейсы:
Код
C++ (Qt)
   enum NGroupDataTypes {
       eNSimpleDataTypes
   };
 
   class INDataTypes
   {
   public:
       virtual ~INDataTypes() { }
 
       virtual qint32 id() const = 0;
       virtual void setId(qint32 id) = 0;
       virtual QString name() const = 0;
       virtual void setName(QString name) = 0;
 
       virtual NGroupDataTypes groupDataTypes() const = 0;
 
   protected:
       //если идентификатор равен -1, значит это либо временная переменная, либо константное значение
       qint32 _id;
       //константные или временные значения имен не имеют, только переменные.
       QString _name;
       //указание на принадлежность к группе типов данных.
       NGroupDataTypes _groupdatatypes;
   };
 
 
   class INSimpleDataTypes : public INDataTypes
   {
   public:
       virtual QString valueToQString() const = 0;
 
   protected:
       //это указывает на константное значение
       bool _constValue;
   };
 

Базовый класс:
Код
C++ (Qt)
   class NSimpleDataTypes : public INSimpleDataTypes
   {
   public:
       NSimpleDataTypes()
       {
           _id = -1; _name = "";
           _constValue = false;
           _groupdatatypes = eNSimpleDataTypes;
       }
 
       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 = "";}
 
       NGroupDataTypes groupDataTypes() const {return _groupdatatypes;}
 
       bool constValue() const {return _constValue;}
       void setConstValue(bool constValue) {_constValue = constValue;}              
   };
 

В производном ничего не менял.

И вот так это используется:
Код
C++ (Qt)
NNumeric  numeric= 5;
INDataTypes *idt = numeric;
bool b = (*idt).groupDataTypes() == eNSimpleDataTypes;
 
Булев b примет истину.

Проблема решена.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Март 27, 2011, 12:01 »

Чем же dynamic_cast не устроил?
Записан
Eten
Гость
« Ответ #3 : Март 27, 2011, 12:44 »

Чем же dynamic_cast не устроил?
А тем, что мне надо проверить, а не пытаться привести в тип до проверки (так быстрее). Да и в программе, с использованием перечисления, код стал понятнее. А все dynamic_cast я выполняю только тогда, когда знаю к чему привести.

Да и мне тут ваши коллеги еще в прошлых темах сказали, что использование dynamic_cast в проверке на класс для использования dynamic_cast с привидением на проверяемый класс, работа для не ленивых программистов. Т.е. выполняется дважды. А через перечисление все работает без лишних наворотов и в самой программе оказалось оно нужным, т.е. не лишним. typeid проверяет на конкретные классы сам. Так что dynamic_cast для проверки на тип это уже лишнее, а вот для самого привидения в тип, это как раз то, что нужно.  Подмигивающий

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Март 27, 2011, 13:25 »

Чем же dynamic_cast не устроил?
А тем, что мне надо проверить, а не пытаться привести в тип до проверки (так быстрее). Да и в программе, с использованием перечисления, код стал понятнее. А все dynamic_cast я выполняю только тогда, когда знаю к чему привести.

Да и мне тут ваши коллеги еще в прошлых темах сказали, что использование dynamic_cast в проверке на класс для использования dynamic_cast с привидением на проверяемый класс, работа для не ленивых программистов. Т.е. выполняется дважды. А через перечисление все работает без лишних наворотов и в самой программе оказалось оно нужным, т.е. не лишним. typeid проверяет на конкретные классы сам. Так что dynamic_cast для проверки на тип это уже лишнее, а вот для самого привидения в тип, это как раз то, что нужно.  Подмигивающий
А почему просто не сказать "я уже написал и оно (как-то) работает. Переделывать снова я НЕ БУДУ!!" (или просто промолчать). К чему этот анекдот "сначала (самому) проверить а затем уж dynamic_cast" ?   Улыбающийся

Разумеется Вы имеете право на собственное мнение и можете принимать даваемые советы или нет. Но сначала надо открыть книжку и прочитать, это недолго и несложно. А потом уж спорить, отстаивать свою точку зрения и.т.д.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #5 : Март 27, 2011, 15:06 »

Непонял:
Цитировать
А тем, что мне надо проверить, а не пытаться привести в тип до проверки (так быстрее). Да и в программе, с использованием перечисления, код стал понятнее. А все dynamic_cast я выполняю только тогда, когда знаю к чему привести.
Если заранее известно к чему нужно привести базовай класс, то dynamic_cast избыточен: как раз для этого предназначен static_cast.

И зачем в INDataTypes делать функции
Код
C++ (Qt)
virtual qint32 id() const = 0;
       virtual void setId(qint32 id) = 0;
       virtual QString name() const = 0;
       virtual void setName(QString name) = 0;
 
виртуальными?
Можно вполне сделать так:
Код
C++ (Qt)
class INDataTypes
   {
   public:
       virtual ~INDataTypes() { }
 
       qint32 id() const { return _id; }
       void setId(qint32 id) { _id = id; }
       QString name() const { return _name; }
       void setName(QString name) { _name = name;}
 
       virtual NGroupDataTypes groupDataTypes() const = 0; // Оставить только эту фиртуальной
protected:
//если идентификатор равен -1, значит это либо временная переменная, либо константное значение
       qint32 _id;
       //константные или временные значения имен не имеют, только переменные.
       QString _name;
   };
 
Тогда, например в  NSimpleDataTypes:
Код
C++ (Qt)
class NSimpleDataTypes : public INSimpleDataTypes
   {
   public:
       NSimpleDataTypes()
       {
           _id = -1; _name = "";
           _constValue = false;
           //_groupdatatypes = eNSimpleDataTypes; Нафига лишняя переменная?
       }
 
       NGroupDataTypes groupDataTypes() const {return eNSimpleDataTypes; /*_groupdatatypes; */ }
 
/* Это тоже лишнее */
       bool constValue() const {return _constValue;}
       void setConstValue(bool constValue) {_constValue = constValue;}              
   };
 
« Последнее редактирование: Март 27, 2011, 15:08 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Март 27, 2011, 15:41 »

Если заранее известно к чему нужно привести базовай класс, то dynamic_cast избыточен: как раз для этого предназначен static_cast.
static_cast ничего не проверит, он просто "приведет" если типы позволяют, NULL он не вернет
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #7 : Март 27, 2011, 15:55 »

Если заранее известно к чему нужно привести базовай класс, то dynamic_cast избыточен: как раз для этого предназначен static_cast.
static_cast ничего не проверит, он просто "приведет" если типы позволяют, NULL он не вернет
Согласен) В том то всё и дело, что проверка не нужна, если заранее известно к чему приводить)
Или мы о разном говорим?
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Eten
Гость
« Ответ #8 : Март 27, 2011, 16:06 »

m_ax, переменная _groupdatatypes вовсе не лишняя, она то мне и помогла разобраться с определением принадлежности класса к группе. А в классе NSimpleDataTypes определяется функция groupDataTypes, которая выдает значение той самой переменной. Т.е. _groupdatatypes инициализуемая в конструкторе указывает на то, что все наследуемые от NSimpleDataTypes производные классы будут принадлежать к eNSimpleDataTypes, с которыми программа работает, через интерфейсы определенным образом. Т.е. для это оказался самый практичный способ решения проблемы и к тому же удобный во многих отношениях, если заглядывать вперед.

Igors , я никого не хотел обижать или с кем-то спорить. Но ваш вопрос показался мне странным (ведь на вопросы стоит отвечать), поэтому мне показалось, что я что-то мог упустить из внимания.  Подмигивающий

З.Ы.
За советы и рекомендации разумеется, огромное спасибо. Код дальше изменять здесь уже не стану мне достаточно и той реализации, к которой пришел.  Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #9 : Март 27, 2011, 16:15 »

m_ax, переменная _groupdatatypes вовсе не лишняя, она то мне и помогла разобраться с определением принадлежности класса к группе. А в классе NSimpleDataTypes определяется функция groupDataTypes, которая выдает значение той самой переменной. Т.е. _groupdatatypes инициализуемая в конструкторе указывает на то, что все наследуемые от NSimpleDataTypes производные классы будут принадлежать к eNSimpleDataTypes, с которыми программа работает, через интерфейсы определенным образом. Т.е. для это оказался самый практичный способ решения проблемы и к тому же удобный во многих отношениях, если заглядывать вперед.
Всё равно не понял)
Чем, например это:
Код
C++ (Qt)
NSimpleDataTypes()
       {
           _id = -1; _name = "";
           _constValue = false;
           _groupdatatypes = eNSimpleDataTypes;
       }
 
       NGroupDataTypes groupDataTypes() const {return _groupdatatypes;  }
 

Отличается от:
Код
C++ (Qt)
NSimpleDataTypes()
       {
           _id = -1; _name = "";
           _constValue = false;
       }
 
       NGroupDataTypes groupDataTypes() const {return eNSimpleDataTypes;  }
 
?
И потом, надо помнить, что вызов виртуальной функции обходится дороже, вызова обычной функции и там где есть возможность обойтись без виртуальных функций лучше обходится без них.
У вас же как раз такой случай в отношении 3 функций:
Код
C++ (Qt)
virtual void setId(qint32 id) = 0;
       virtual QString name() const = 0;
       virtual void setName(QString name) = 0;
 
 
Какой по вашему смысл в том, чтобы они были виртуальными? Чтобы в наследуемых классах каждый раз переопределять их одинаковым образом увеличивая при этом число строк кода и снижая производительность при их вызове? 
« Последнее редактирование: Март 27, 2011, 16:46 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Март 27, 2011, 16:31 »

Igors , я никого не хотел обижать или с кем-то спорить. Но ваш вопрос показался мне странным (ведь на вопросы стоит отвечать), поэтому мне показалось, что я что-то мог упустить из внимания.  Подмигивающий
Я и не обижаюсь  Улыбающийся

Код дальше изменять здесь уже не стану мне достаточно и той реализации, к которой пришел.  Улыбающийся
Это совершенно нормально, никто и не думает настаивать, ведь проект Ваш

Единственная причина по которой я пишу - это сентенции типа таких
...Т.е. для это оказался самый практичный способ решения проблемы и к тому же удобный во многих отношениях, если заглядывать вперед.
Никто не осуждает Вас за недостаток опыта в ++, но зачем прикрывать это словами "самый практичный", "удобный во многих.."?  Улыбающийся Ваш способ давно известен и квалифицируется библией как "издевательство над принципами ООП"
Записан
Eten
Гость
« Ответ #11 : Март 27, 2011, 17:49 »

Спасибо, m_ax, все никак не отвыкну от привычек C#-а.
Записан
alexcpp
Гость
« Ответ #12 : Апрель 05, 2011, 00:11 »

http://www.boost.org/doc/libs/1_46_1/libs/type_traits/doc/html/boost_typetraits/reference/is_base_of.html
иникакова рунтима. все в компилетиме. никакова дапалнительнага разхода CPU.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #13 : Апрель 05, 2011, 00:29 »

http://www.boost.org/doc/libs/1_46_1/libs/type_traits/doc/html/boost_typetraits/reference/is_base_of.html
иникакова рунтима. все в компилетиме. никакова дапалнительнага разхода CPU.
Всё же здесь немного другой случай. Здесь и так известно к чему приводить. И приводится без всякого рантайма)

Кстати, type_traits: можно юзать в c++0x
#include <tr1/type_traits>
 Подмигивающий
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
alexcpp
Гость
« Ответ #14 : Апрель 05, 2011, 14:40 »

#include <type_traits>

у вас наверна очень давний компелатор.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.383 секунд. Запросов: 23.