Вопросы про novtable
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 25.10.19 13:37
Оценка:
Если __declspec(novtable) реально уменьшает размер бинарников, то почему оптимизатор не юзает эту штуку по своему уразумению?

Вот у меня есть класс вида:

class t_err_records_r
{
 public:
  virtual ~t_err_records_r(){;}

  //interface ------------------------------------------------------------
  virtual size_t get_record_count()const=0;

  virtual t_err_record::self_ptr get_record(size_t record_num)const=0;
};//class t_err_records_r


Добавил к нему и еще к паре аналогичных мелких абстрактных классов __declspec(novtable), бинарник (VS2019) уменьшился на килобайт.

Причем один из этих классов наследует t_err_records_r — добавляется еще один абстрактный виртуальный метод.

---
Еще вопросы по novtable. Возможны ли засады:

2. С виртуальными деструкторами novtable-классов?

3. С dynamic_cast-ом?

4. C абстрактным классом, экспортируемым DLL-ю?

На сколько я понимаю, в конструкторе/деструкторе novtable-класса не стоит:
— обращаться (напрямую/косвенно) к виртуальным методам
— юзать dynamic_cast к самому себе или родительским классам

и тогда проблем не будет.

Так что, в принципе, остается только первый вопрос только про оптимизатор. Или я его (оптимизатор) не правильно готовлю?

PS. C dynamic_cast я провел доп. эксперимент. Я его тут ниже, отдельно опубликую.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Отредактировано 25.10.2019 13:47 DDDX . Предыдущая версия .
Re: Вопрос про novtable. dynamic_cast и деструктор
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 25.10.19 13:47
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Еще вопросы по novtable. Возможны ли засады:


КД>2. С виртуальными деструкторами novtable-классов?


КД>3. С dynamic_cast-ом?


  Я тут небольшой тестовый пример накатал.
////////////////////////////////////////////////////////////////////////////////

#include <iostream>

////////////////////////////////////////////////////////////////////////////////
//class t_object

class __declspec(novtable) t_object
{
 public:
  virtual ~t_object()
  {
   std::cout<<"~t_object"<<std::endl;
  }

  virtual int get_id()const=0;
};//class t_exec_base

////////////////////////////////////////////////////////////////////////////////
//class t_exec_base

class __declspec(novtable) t_exec_base:public t_object
{
 public:
  virtual void exec()=0;
};//class t_exec_base

////////////////////////////////////////////////////////////////////////////////
//class t_exec

class t_exec:public t_exec_base
{
 public:
  virtual ~t_exec()
  {
   std::cout<<"~t_exec"<<std::endl;
  }

  virtual int get_id()const override
  {
   return 1;
  }

  virtual void exec()override
  {
   std::cout<<"EXEC"<<std::endl;
  }
};//class t_exec

////////////////////////////////////////////////////////////////////////////////

int main()
{
 {
  t_exec x;

  t_object* const obj=&x;

  t_exec_base* const p=dynamic_cast<t_exec_base*>(obj);

  p->exec();
 }

 {
  std::cout<<"------------------"<<std::endl;

  t_object* p=new t_exec();

  delete p;
 }

 return 0;
}//main

////////////////////////////////////////////////////////////////////////////////

Проблем с dynamic_cast и виртуальным деструктором не наблюдается (VS2019):

Вывод:
EXEC
~t_exec
~t_object
------------------
~t_exec
~t_object


Надо бы еще накатать тест, в котором t_object и t_exec_base экспортируются из DLL. Но, полагаю, там тоже проблем не будет...
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Вопросы про novtable. default constructor.
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.10.19 08:37
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Если __declspec(novtable) реально уменьшает размер бинарников, то почему оптимизатор не юзает эту штуку по своему уразумению?


Интересно, а почему компилятор (VC) не позволяет запретить default-конструктор в классе с novtable и без каких-либо данных?

class __declspec(novtable) t_myclass
{
 public:
  t_myclass()=delete;

  virtual void method()=0;
};

При компиляции конструктора производного класса вылазит ошибка.

Ответ я, собственно, знаю — потому что компилятор туповат.

Но есть сомнения — может это я хочу странного?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Отредактировано 28.10.2019 8:37 DDDX . Предыдущая версия .
Re: Вопросы про novtable
От: rg45 СССР  
Дата: 28.10.19 09:53
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Еще вопросы по novtable. Возможны ли засады:

КД>2. С виртуальными деструкторами novtable-классов?
КД>3. С dynamic_cast-ом?
КД>4. C абстрактным классом, экспортируемым DLL-ю?

Никаких засад не будет, если не создается объектов с таким статическим типом. Для этого достаточно просто следить, чтоб такие атрибуты пименялись только к абстрактным классам.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Вопросы про novtable. default constructor.
От: rg45 СССР  
Дата: 28.10.19 10:00
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Интересно, а почему компилятор (VC) не позволяет запретить default-конструктор в классе с novtable и без каких-либо данных?


КД>
КД>class __declspec(novtable) t_myclass
КД>{
КД> public:
КД>  t_myclass()=delete;

КД>  virtual void method()=0;
КД>};
КД>


КД>При компиляции конструктора производного класса вылазит ошибка.

КД>Ответ я, собственно, знаю — потому что компилятор туповат.
КД>Но есть сомнения — может это я хочу странного?

Так novtable тут вообще ни при чем. Просто конструктор производного класса неявно использует конструктор по умолчанию базового класса, который у тебя запрещен. Чтобы избежать ошибки, нужно явно использовать какой-нибудь другой конструктор:

class __declspec(novtable) I
{
public:

    I() = delete;
    I(int) {}

    virtual void foo() = 0;
};

class B : public I
{
public:
    void foo() override {}

    B() : I(42) {}
};

P.S. Если тебе нужно только защититься от создания объектов базового класса, просто сделай дефолтный конструктор защищенным. Хотя для абстрактных классов это излишняя мера, поскольку компилятор и так не позволит создать экземпляр абстрактного класса.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 28.10.2019 10:08 rg45 . Предыдущая версия . Еще …
Отредактировано 28.10.2019 10:08 rg45 . Предыдущая версия .
Отредактировано 28.10.2019 10:01 rg45 . Предыдущая версия .
Отредактировано 28.10.2019 10:01 rg45 . Предыдущая версия .
Re[3]: Вопросы про novtable. default constructor.
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.10.19 10:07
Оценка:
Здравствуйте, rg45, Вы писали:

R>Так novtable тут вообще ни при чем. Просто конструктор производного класса неявно использует конструктор по умолчанию базового класса, который у тебя запрещен. Чтобы избежать ошибки, нужно явно использовать какой-нибудь другой конструктор:


Это понятно.

Но я хотел описать чистый интерфейс (абстрактный класс с novtable), для которого компилятор не будет генерировать какие-либо методы.

Ни конструкторов, ни деструктора, ни операторов.

В общем — хочу "explicit class"
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Вопросы про novtable. default constructor.
От: rg45 СССР  
Дата: 28.10.19 10:23
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Но я хотел описать чистый интерфейс (абстрактный класс с novtable), для которого компилятор не будет генерировать какие-либо методы.

КД>Ни конструкторов, ни деструктора, ни операторов.
КД>В общем — хочу "explicit class"

Ну это скорее похоже на интерфейсы C# и Java. Ну нету в C++ интефейсов, как таковых. Просто ни у кого нет достаточной мотивации, чтобы из вводить.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Вопросы про novtable. default constructor.
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.10.19 10:30
Оценка: :)
Здравствуйте, rg45, Вы писали:

КД>>Но я хотел описать чистый интерфейс (абстрактный класс с novtable)


R>Ну нету в C++ интефейсов, как таковых.


-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Вопросы про novtable
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 28.10.19 20:07
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Добавил к нему и еще к паре аналогичных мелких абстрактных классов __declspec(novtable), бинарник (VS2019) уменьшился на килобайт.


Хм. У меня в последнем небольшом проекте только один абстрактный класс, бинарники (x86/x64) — 130/150 кб. Добавил novtable — оба уменьшились на три килобайта (VS 2008).

Я про давно novtable знал, но искренне полагал, что он ощутим только на наборах из десятков и более классов, а поди ж ты...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.