Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Виртуальный и inline метод 
:(
    Опции темы
SABROG
  Дата 24.7.2009, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Есть у меня такая бяка.

Код

class Base
{
public:
    Base()
    {
    }
    void parse()
    {
        for (int i=0; i < 2; ++i) {
            if (custom(i))
                break;
        }
    }
    virtual bool custom(int i);
};

class MyClass : public Base
{
public:
    MyClass()
    {
    }
    inline bool custom(int i)
    {
        switch (i)
        {
            case 0:
                qDebug() << i;
                return false;
                break;
            case 1:
                qDebug() << i;
                return true;
                break;
            default:
                break;
        }
        return true;
    }
};


Задача в том, чтобы сделать скажем 10-20 классов наследников от Base. И у всех этих классов будет единый код parse(), а вот метод custom() я хочу переопределить в каждом классе. Чтобы чуток убыстрить код я решил метод сделать inline. Вопрос заключается в том как поведет себя компилятор в этом случае. Ведь изначально код метода parse() - общий для всех экземляров, меняется только объект, но если идет inline подстановка кода внутрь метода каждого экземляра класса на базе Base, не получится ли так, что код блока for(){} будет продублирован 10-20 раз в исполнимом файле для каждого класса? Или компилятор просто проигнорирует ключевое слово inline


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Alexeis
Дата 24.7.2009, 20:47 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



  Inline нестрогая директива, а virtual строгая. Поскольку они взаимоисключающие, то сработает тока virtual.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
SABROG
Дата 24.7.2009, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Спасибо. Жалко, что у компилятора (gcc) по этому поводу варнингов не выводится.

Еще один вопрос. Как компилятор разрулит ситуацию, ведь указатель на метод custom() у каждого класса будет разным, не будет ли в этом случае весь код из parse() дублироваться в новые классы?

Код

    void parse()
    {
        for (int i=0; i < 2; ++i) {
            if (custom(i))
                break;
        }
    }


Это сообщение отредактировал(а) SABROG - 24.7.2009, 21:14


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
azesmcar
Дата 24.7.2009, 21:22 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(Alexeis @  24.7.2009,  20:47 Найти цитируемый пост)
  Inline нестрогая директива, а virtual строгая. Поскольку они взаимоисключающие, то сработает тока virtual. 

Они не взаимоисключающие, вызов виртуальной функции может быть встроен в некоторых случаях. Но ключевое слово inline для этого писать совершенно не обязательно, позволь компилятору самому решить. Функция определена в самом классе - этого достаточно.

Цитата(SABROG @  24.7.2009,  21:00 Найти цитируемый пост)
Еще один вопрос. Как компилятор разрулит ситуацию, ведь указатель на метод custom() у каждого класса будет разным, не будет ли в этом случае весь код из parse() дублироваться в новые классы?

Нет, функция parse одна, с чего ей дублироваться?

Это сообщение отредактировал(а) azesmcar - 24.7.2009, 21:28
PM   Вверх
kamre
Дата 24.7.2009, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 330
Регистрация: 24.3.2006

Репутация: 1
Всего: 13



Цитата(SABROG @ 24.7.2009,  20:40)
Задача в том, чтобы сделать скажем 10-20 классов наследников от Base. И у всех этих классов будет единый код parse(), а вот метод custom() я хочу переопределить в каждом классе. Чтобы чуток убыстрить код я решил метод сделать inline.

В этом случае может подойти static polymorphism и Curiously recurring template pattern. Компилятор может в принципе и заинлайнить все эти custom() функции.
PM MAIL   Вверх
Alexeis
Дата 24.7.2009, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(azesmcar @  24.7.2009,  20:22 Найти цитируемый пост)
Они не взаимоисключающие, вызов виртуальной функции может быть встроен в некоторых случаях.

  Каким образом? Ведь суть позднего связывания в том, что во время компиляции неизвестно какой реально метод будет вызван, поэтому и вставляется код который ищет адрес функции в VMT. Внутри метода этого класса 100% будет вызван виртуально. Инлайн возможен только если объект создан статически и тут же вызван его метод "через точку". Я таких вещей не проверял, но из курса по ООП я помню то что виртуальная функция всегда должна вызываться как виртуальная.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
azesmcar
Дата 24.7.2009, 22:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(Alexeis @  24.7.2009,  22:18 Найти цитируемый пост)

  Каким образом? Ведь суть позднего связывания в том, что во время компиляции неизвестно какой реально метод будет вызван, поэтому и вставляется код который ищет адрес функции в VMT. Внутри метода этого класса 100% будет вызван виртуально. Инлайн возможен только если объект создан статически и тут же вызван его метод "через точку". Я таких вещей не проверял, но из курса по ООП я помню то что виртуальная функция всегда должна вызываться как виртуальная. 

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

B b;
b.f();

этот вызов вполне может быть встроен
Код

std::string name;
std::cin >> name;
base* b = factory.create(name);
b->f();

а тут разумеется встроить не сможет даже самый гениальный компилятор
(тут нужен дар предвидения  smile )

Цитата

Инлайн возможен только если объект создан статически и тут же вызван его метод "через точку". 

ну да, я как раз об этом.

Это сообщение отредактировал(а) azesmcar - 24.7.2009, 22:31
PM   Вверх
mes
Дата 24.7.2009, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  24.7.2009,  20:22 Найти цитируемый пост)
Они не взаимоисключающие, вызов виртуальной функции может быть встроен в некоторых случаях. 

 smile, в тех случаях, когда компилятор может определить отсутствие полиморфного вызова.

Цитата(kamre @  24.7.2009,  20:30 Найти цитируемый пост)
В этом случае может подойти static polymorphism и Curiously recurring template pattern. 

 smile, но только с потерей преимуществ динамического полиморфизма, т.е  нельзя будет в рантайме пользовать объект через интерфейс базового класса.

Добавлено через 1 минуту и 15 секунд
Цитата(Alexeis @  24.7.2009,  21:18 Найти цитируемый пост)
Инлайн возможен только если объект создан статически и тут же вызван его метод "через точку". 

 smile 


--------------------
PM MAIL WWW   Вверх
SABROG
Дата 25.7.2009, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



А вообще возможно завести контейнер, который содержал бы указатели на базовый класс и получая указатель через этот контейнер использовать методы производного класса (upcast?), без RTTI?

Просто я не совсем понимаю как это работает на Java:

Базовый класс
Код

public interface ComponentParser {
  
  /**
   * Parse some XML data using the supplied stax reader.
   * @param staxXmlReader STAX reader.
   * @throws XMLStreamException
   */
  public void parse(XMLStreamReader staxXmlReader) throws XMLStreamException;
 
}


Производный класс:

Код

public class AuthorParser implements ComponentParser{

  
  public void parse(XMLStreamReader staxXmlReader) throws XMLStreamException{
    
      // read name
      StaxUtil.moveReaderToElement("name",staxXmlReader);
      String name = staxXmlReader.getElementText();
      
      // read email
      StaxUtil.moveReaderToElement("email",staxXmlReader);
      String email = staxXmlReader.getElementText();
      
      // Do something with author data...
  }
  
 

}



Вызов переопределенного метода parse() через базовый класс, как такое возможно?
Код

          if (delegates.containsKey(element)) {
            ComponentParser parser = (ComponentParser) delegates.get(element);
            parser.parse(staxXmlReader);
          } 


delegates - контейнер map.

Это сообщение отредактировал(а) SABROG - 25.7.2009, 18:11


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
mes
Дата 25.7.2009, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SABROG @  25.7.2009,  17:03 Найти цитируемый пост)
А вообще возможно завести контейнер, который содержал бы указатели на базовый класс и получая указатель через этот контейнер использовать методы производного класса (upcast?), без RTTI?

нет.. но можно постораться сократить кол-во виртуальных вызовов.

Добавлено через 2 минуты и 20 секунд
Цитата(SABROG @  25.7.2009,  17:03 Найти цитируемый пост)
Просто я не совсем понимаю как это работает на Java:

так на Яве по умолчанию вроде ж все методы виртуальные smile


Это сообщение отредактировал(а) mes - 25.7.2009, 18:12


--------------------
PM MAIL WWW   Вверх
SABROG
Дата 25.7.2009, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(mes @  25.7.2009,  18:12 Найти цитируемый пост)
так на Яве по умолчанию вроде ж все методы виртуальные


Если я сделаю базовый класс полностью виртуальным мне это поможет? smile

Цитата(mes @  25.7.2009,  18:12 Найти цитируемый пост)
нет.. но можно постораться сократить кол-во виртуальных вызовов.


Тут я не уловил мысли. В принципе у меня один метод виртуальный, который переопределен в производном классе. Если я вызову не виртуальный метод parse() базового класса, в котором используется переопределенный виртуальный метод производного класса это будет работать?


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
mes
Дата 25.7.2009, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SABROG @  25.7.2009,  17:35 Найти цитируемый пост)

Тут я не уловил мысли.


Цитата(SABROG @  24.7.2009,  19:40 Найти цитируемый пост)
. И у всех этих классов будет единый код parse(), а вот метод custom() я хочу переопределить в каждом классе


Цитата(SABROG @  24.7.2009,  19:40 Найти цитируемый пост)
    void parse()
    {
        for (int i=0; i < 2; ++i) {
            if (custom(i))
                break;
        }
    }
  virtual bool custom(int i);


вот тут многоразовый вызов виртуального метода custom. Хотя достаточно сделать виртуальным parse (), а чтоб не повторять код в теле  функции применить шаблоны, возможно CRT Pattern.
Вообщем мысль в том, чтоб правильно организовать архитектуру, избежав лишних виртуальных вызовов.






--------------------
PM MAIL WWW   Вверх
SABROG
Дата 25.7.2009, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(mes @  25.7.2009,  18:40 Найти цитируемый пост)
вот тут многоразовый вызов виртуального метода custom. Хотя достаточно сделать виртуальным parse (),


Я на это пойтить не могу, смысл всего в том, чтобы избежать дублирования кода. Если я сделаю parse() виртуальным, то мне придется в 20 классах дублировать цикл for().

Ладно, может быть тогда посоветуете какой-нибудь другой способ, чтобы избежать такого:

Код

void Tag1()
{
    while(!atEnd) {
        ...
    }
}

void Tag2()
{
    while(!atEnd) {
        ...
    }
}

void Tag3()
{
    while(!atEnd) {
        ...
    }
}

void Tag4()
{
    while(!atEnd) {
        ...
    }
}


Пытаюсь написать класс, который было бы удобно использовать с StAX xml парсером, но если брать во внимание саму технологию, то отпарсить сложный xml файл с большой глубиной уровней задача не из легких.

Ссылка для ознакомления: 
http://www.devx.com/Java/Article/30298/0/page/2 - статья про StAX в Java

А это то, как выглядит парсинг xml'я простой структуры, всего 3 вложенных цикла while. У меня же этих циклов намного больше.

Код

        QXmlStreamReader xml(data);
        while (!xml.atEnd()) {
            xml.readNext();
            if (xml.tokenType() == QXmlStreamReader::StartElement) {
                if (xml.name() == "city") {
                    city = GET_DATA_ATTR;
                    setWindowTitle(city);
                }
                if (xml.name() == "unit_system")
                    unitSystem = xml.attributes().value("data").toString();
                // Parse current weather conditions
                if (xml.name() == "current_conditions") {
                    while (!xml.atEnd()) {
                        xml.readNext();
                        if (xml.name() == "current_conditions")
                            break;
                        if (xml.tokenType() == QXmlStreamReader::StartElement) {
                            if (xml.name() == "condition") {
                                m_conditionItem->setPlainText(GET_DATA_ATTR);
                            }
                            if (xml.name() == "icon") {
                                QString name = extractIcon(GET_DATA_ATTR);
                                if (!name.isEmpty()) {
                                    delete m_iconItem;
                                    m_iconItem = new QGraphicsSvgItem(name);
                                    m_scene.addItem(m_iconItem);
                                    m_iconItem->setParentItem(m_statusItem);
                                }
                            }
                            if (xml.name() == "temp_c") {
                                QString s = GET_DATA_ATTR + QChar(176);
                                m_temperatureItem->setPlainText(s);
                            }
                        }
                    }
                }
                // Parse and collect the forecast conditions
                if (xml.name() == "forecast_conditions") {
                    QGraphicsTextItem *dayItem  = 0;
                    QGraphicsSvgItem *statusItem = 0;
                    QString lowT, highT;
                    while (!xml.atEnd()) {
                        xml.readNext();
                        if (xml.name() == "forecast_conditions") {
                            if (dayItem && statusItem &&
                                !lowT.isEmpty() && !highT.isEmpty()) {
                                m_dayItems << dayItem;
                                m_conditionItems << statusItem;
                                QString txt = highT + '/' + lowT;
                                QGraphicsTextItem* rangeItem;
                                rangeItem = m_scene.addText(txt);
                                rangeItem->setDefaultTextColor(textColor);
                                m_rangeItems << rangeItem;
                                QGraphicsRectItem *box;
                                box = m_scene.addRect(0, 0, 10, 10);
                                box->setPen(Qt::NoPen);
                                box->setBrush(Qt::NoBrush);
                                m_forecastItems << box;
                                dayItem->setParentItem(box);
                                statusItem->setParentItem(box);
                                rangeItem->setParentItem(box);
                            } else {
                                delete dayItem;
                                delete statusItem;
                            }
                            break;
                        }
                        if (xml.tokenType() == QXmlStreamReader::StartElement) {
                            if (xml.name() == "day_of_week") {
                                QString s = GET_DATA_ATTR;
                                dayItem = m_scene.addText(s.left(3));
                                dayItem->setDefaultTextColor(textColor);
                            }
                            if (xml.name() == "icon") {
                                QString name = extractIcon(GET_DATA_ATTR);
                                if (!name.isEmpty()) {
                                    statusItem = new QGraphicsSvgItem(name);
                                    m_scene.addItem(statusItem);
                                }
                            }
                            if (xml.name() == "low")
                                lowT = toCelcius(GET_DATA_ATTR, unitSystem);
                            if (xml.name() == "high")
                                highT = toCelcius(GET_DATA_ATTR, unitSystem);
                        }
                    }
                }

            }
        }



Это сообщение отредактировал(а) SABROG - 25.7.2009, 19:03


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
mes
Дата 25.7.2009, 19:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SABROG @  25.7.2009,  17:55 Найти цитируемый пост)
Если я сделаю parse() виртуальным, то мне придется в 20 классах дублировать цикл for().


А если сделать две Parse  ? одна для вызова виртуальная, другая шаблонная для имплементации ?

Вот в упрощенном виде :

Код

struct IBase
{
   virtual void Parse ()=0;
};

template <class T> void doParse (T& obj)
{
           for (int i=0; i < 2; ++i) 
             if (obj.custom(i))  break;
        
}

struct Der : IBase
{
    virtual void Parse ()     { doParse(*this); }
            bool Custom (int) { ... }
};





Это сообщение отредактировал(а) mes - 25.7.2009, 20:21


--------------------
PM MAIL WWW   Вверх
Любитель
Дата 28.7.2009, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 24
Всего: 92



Цитата(mes @  25.7.2009,  19:19 Найти цитируемый пост)
А если сделать две Parse  ? одна для вызова виртуальная, другая шаблонная для имплементации ?

Именно так обычно и делается. У Саттера вроде была фраза о том, чтобы делать виртуальными только прайват-методы. А паблик/проектед обёртки проверяют аргументы и выполняют некий общий, ненастраиваемый код (это правда специфика С++ - не во всех ОО-моделях прайват-методы вообще могут работать как виртуальные).


--------------------
PM MAIL ICQ Skype   Вверх
mes
Дата 28.7.2009, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Любитель @  28.7.2009,  13:36 Найти цитируемый пост)
У Саттера вроде была фраза о том, чтобы делать виртуальными только прайват-методы.

Это несколько другая задача (можно сказать обратная нашей)- паттерн невиртуальный интерфейс. 
у нас "проблема" - лишние виртуальные вызовы. Данный паттерн ничем в данном вопросе помочь не может smile



--------------------
PM MAIL WWW   Вверх
Любитель
Дата 28.7.2009, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 24
Всего: 92



Сорри, я невнимательно прочитал твой прошлый пост :(
Я думал речь о том, как обеспечить настраиваемость без дублирования кода, а не о минимизации виртуальных вызовов.
Тогда речь о другом - а стоит ли это делать вообще? Ведь parse (пусть и маленький) всё равно придётся писать везде в этом случае. Как я понимаю, речь о прикладном приложении, причём на Qt - там найдётся куча гораздо более узких мест..


--------------------
PM MAIL ICQ Skype   Вверх
mes
Дата 28.7.2009, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Любитель @  28.7.2009,  14:16 Найти цитируемый пост)
Ведь parse (пусть и маленький) всё равно придётся писать везде в этом случае.

не обязательно.. вот пример, заодно и тс. будет легче 
Код

#include <iostream>

struct IParser { virtual void Parse () =0; };

template <class T, class Base>
class CParserOneTemplate : public Base
{
     public:
           void Parse ()  { crtBegin(); for (unsigned i=0; i<crtCount(); ++i) crtBody(i); crtEnd(); }

// вспомогательные функции статического виртуального вызова
    private:
           void crtBegin ()           { static_cast<T*>(this)->Begin();  }
           void crtBody  (unsigned i) { static_cast<T*>(this)->Body(i);  }
           void crtEnd   ()           { static_cast<T*>(this)->End();    }

           unsigned crtCount  ()      { static_cast<T*>(this)->Count();  }

// заготовки могут отсутствовать в шаблоне, но тогда обязательно должны быть реализованы
      public:
           void Begin ()           { std::cout << "[template-begin] "; }
           void Body  (unsigned i) { std::cout << "[template-body " << i << " ] ";  }
           void End  ()            { std::cout << "[template-end] ";   }

           unsigned Count  ()      { return 3; }
};

class CParserOneA : public CParserOneTemplate<CParserOneA, IParser>
{
    public:
       void Begin ()           { std::cout << "[A begin] "; }
       void Body  (unsigned i) { std::cout << "[A body " << i << " ] ";  }
       void End  ()            { std::cout << "[A end] ";   }

       unsigned Count  ()      { return 5; }
};

// если нам для каких то функций подходит базовая реализация, то нам ее реализовывать не надо 
class CParserOneB : public CParserOneTemplate<CParserOneB, IParser>  
{
    public:
       void Body  (unsigned i) { std::cout << "[B body " << i << " ] ";  }

       unsigned Count  ()      { return 2; }
};


int main(int argc, char* argv[])
{
  std::auto_ptr<IParser> p1 ( new CParserOneA() );
  std::auto_ptr<IParser> p2 ( new CParserOneB() );

  p1->Parse();
  std::cout << std::endl;

  p2->Parse();
  std::cout << std::endl;
 
  return 0;
}


как видите, никаких  лишних повторений исходного кода
smile



Это сообщение отредактировал(а) mes - 29.7.2009, 03:57


--------------------
PM MAIL WWW   Вверх
Любитель
Дата 28.7.2009, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 24
Всего: 92



Да, красиво smile

Единственное - всё-таки увлекаться таким не стоит. Пусть код писать не будем, но для каждого цикла ведь весь цикл будет дублироваться (придесятке классов это несущественно, конечно).

Это сообщение отредактировал(а) Любитель - 28.7.2009, 17:06


--------------------
PM MAIL ICQ Skype   Вверх
mes
Дата 28.7.2009, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Любитель @  28.7.2009,  15:59 Найти цитируемый пост)
Пусть код писать не будем, но для каждого цикла ведь весь цикл будет дублироваться (придесятке классов это несущественно, конечно).

ну это естественно, ради одного приходится жертвовать другим. Тут уж пусть тс. решает что ему важней: избежать лишних виртуальных вызовов или сэкономить на объеме машинного кода (излишки которого в общем случае для данной задачи минимальны)
smile


Это сообщение отредактировал(а) mes - 28.7.2009, 18:28


--------------------
PM MAIL WWW   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1316 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.