Название: Использование чистой виртуальной функции в конструкторе Отправлено: lcs-perm от Май 18, 2013, 07:20 Добрый день.
Пытаюсь разобраться со следующим кодом: Код: #include <iostream> Код: In constructor 'AbstractClass::AbstractClass()': Помогите разобраться, пожалуйста Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Странник от Май 18, 2013, 08:07 ну а что вы ожидали получить, вызывая чисто виртуальную функцию virtual void AbstractClass::AbstractFunc() = 0, реализация для которой отсутствует? вы должны реализовать перегруженную функцию в наследнике AbstractClass и вызывать ее в конструкторе наследника для получения желаемого эффекта. также вы сможете обращаться к ней посредством указателя типа базового класса на объект наследника.
Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: lcs-perm от Май 18, 2013, 08:30 ну а что вы ожидали получить, вызывая чисто виртуальную функцию virtual void AbstractClass::AbstractFunc() = 0, реализация для которой отсутствует? Немного модифицировал код, чтоб компилировалось без ошибокКод: class AbstractClass Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Majestio от Май 18, 2013, 08:33 У наследника функция уже не виртуальная?
Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: lcs-perm от Май 18, 2013, 08:36 У наследника функция уже не виртуальная? Почему не виртуальная. Виртуальность же наследуется.В любом случае - добавление virtual в наследника ничего не дает Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Bepec от Май 18, 2013, 08:42 Сталкивался с такой хотелкой :)
Не пытайтесь вызвать функцию из конструктора - ничего не получится. НО. Если вызвать её QMetaObject::invokeMethod(this, "AbstractFunc"); то тогда всё пройдет так, как вы хотите. Функция в таком случае должна быть слотом. Вкратце - в конструкторе у вас её нет. Но если оставить в очереди событий вызов этой функции, он выполнится сразу после конструктора и функция будет уже не предка, а наследника. PS в С++ такое реализовать будет очень трудно, а в Qt с помощью сигнал-слотов более менее легко. Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Majestio от Май 18, 2013, 08:43 Я знак вопроса лишний поставил. При вызове виртуальной функции из конструктора вызывается та версия, которая определена в данном классе или базового класса, если она в данном классе не перегружена. Вроде так. Для конструктора - формально она не виртуальная.
Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: lcs-perm от Май 18, 2013, 09:15 Bepec. Ну у меня вопрос скорее даже не как реализовать, а скорее из разряда "хочется понять" (хотя и реализовать, конечно, хочется).
Majestio. Попробую поизучать таблицы виртуальных функций C++. Может и пойму, отчего так Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: mutineer от Май 18, 2013, 09:39 Так происходит потому, что во время выполнения конструктора таблица виртуальных функций инициализирована только для текущего класса и его базовых классов. Никакой информации про таблицу виртуальных функций наследников еще нет, поэтому будет вызываться функция текущего конструируемого класса
Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Igors от Май 18, 2013, 10:28 Почему не виртуальная. Виртуальность же наследуется. Дает, но только не в конструкторе/деструкторе базового класса - в этот момент порожденный объект как бы еще не создан (или уже разрушен). Кстати sizeof() также вернет размер базового (а не порожденного) в этот момент.В любом случае - добавление virtual в наследника ничего не дает Это правильно - базовый конструктор выполняется первым и ничего не знает о порожденном. Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: mutineer от Май 18, 2013, 10:30 Igors А что дает добавление virtual в наследнике?
Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Igors от Май 18, 2013, 11:00 Igors А что дает добавление virtual в наследнике? Имеется ввиду "добавление виртуальной ф-ции в наследнике", а не написание для нее слова "virtual", его можно писать или нет - дело вкуса, все равно будет виртуальной.Откуда такое горячее желание "поймать" на незнании азов? :) Хотите поизучать язык - давайте вместе. Напр Так происходит потому, что во время выполнения конструктора таблица виртуальных функций инициализирована только для текущего класса и его базовых классов. Никакой информации про таблицу виртуальных функций наследников еще нет, поэтому будет вызываться функция текущего конструируемого класса А как это протестировать/распечатать? Название: Re: Использование чистой виртуальной функц Отправлено: mutineer от Май 18, 2013, 11:43 Откуда такое горячее желание "поймать" на незнании азов? :) Хотите поизучать язык - давайте вместе. Напр Не было у меня никакого желания "поймать". Спросил на случай вдруг оно что-то экзотическое дает, просто я об этом не знаю Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Old от Май 18, 2013, 12:17 А как это протестировать/распечатать? Для gcc можно так:Код
Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Igors от Май 18, 2013, 14:14 Для gcc можно так: У меня аналогично (несущественная разница в деталях). Правда никакой он не void (не адрес) а, полагаю, индекс/ID (хорошо видно напр в 64). Хотя это не документировано - никогда не видел др реализации ни в одном компилятореНазвание: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Old от Май 18, 2013, 15:06 Правда никакой он не void (не адрес) а, полагаю, индекс/ID (хорошо видно напр в 64). Хотя это не документировано - никогда не видел др реализации ни в одном компиляторе Не знаю куда вы смотрите, но это именно адрес таблицы, в которой лежат адреса функций (в x86_64 в том числе).Код
Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: CuteBunny от Май 22, 2013, 14:43 Добрый день. Пытаюсь разобраться со следующим кодом: Код: #include <iostream> Код: In constructor 'AbstractClass::AbstractClass()': Помогите разобраться, пожалуйста Добавлю свои 5коп. В принципе вы можете определить чисто виртуальную функцию, тогда в этом примере компилятор ошибку не выдаст, но предупреждение все равно будет кидать. Код
Хммм, интересно, если чисто виртуальную функцию можно определить, то в теории её можно вызвать?... Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: lcs-perm от Май 24, 2013, 21:28 После непродолжительных раздумий решил для себя обозначенную в теме проблему следующим образом
Код: #include <iostream> Код: RealClass01 Хотелось бы обсудить, чтобы во-первых - эти самые недостатки увидеть; и, во-вторых - может найдется более приятное для глаза решение Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Igors от Май 25, 2013, 09:53 После непродолжительных раздумий решил для себя обозначенную в теме проблему .. Если поубирать ненужные template и поработать с именами - для глаза будет приятнее. В Вашем решении ничего нового не видно (что не значит "плохо"). После того как все конструкторы отработали - любые виртуалы выполняются "как доктор прописал"...может найдется более приятное для глаза решение Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: lcs-perm от Май 27, 2013, 20:49 Если поубирать ненужные template и поработать с именами - для глаза будет приятнее. В Вашем решении ничего нового не видно (что не значит "плохо"). После того как все конструкторы отработали - любые виртуалы выполняются "как доктор прописал". Ну на оригинальность я и не претендую особо. А вот насчет ненужных template'ов хотелось бы поподробнее.Мне кажется, они обеспечивают возможность не переписывать дружественный конструктор отдельно для каждого класса-наследника. Т.е. именно так, как хочется - один абстрактный конструктор на всех наследников. Или я чего то не понимаю? Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: Igors от Май 28, 2013, 09:57 А вот насчет ненужных template'ов хотелось бы поподробнее. Этого не видноМне кажется, они обеспечивают возможность не переписывать дружественный конструктор отдельно для каждого класса-наследника. Т.е. именно так, как хочется - один абстрактный конструктор на всех наследников. Код: AbstractClass *fc_01 = RealClass01_Create<FactClass01>(new FactClass01); Код Что хотя и примитивно, но куда яснее и короче. Если же метод "неотъемлемая часть" конструктора, то сделать его невиртуальным, при этом виртуальный может просто его вызвать Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: lcs-perm от Май 28, 2013, 16:55 Ну, в классе RealClass01 я использовал абстрактный метод, чтобы проверить абстрактное наследование с глубиной больше чем 1.
А если бы в RealClass01 не было абстрактного метода, то код мог бы быть таким Код: AbstractClass *rc_01 = AbstractClass_Create<RealClass01>(new RealClass01); Конечно, когда конструктор состоит из одного оператора, выгода не очевидна. А вот для достаточно сложных случаев все будет выглядеть совсем по другому. Ну ладно. Спасибо Вам за потраченное время. По крайней мере, у меня была возможность сравнить все плюсы и минусы нескольких подходов. Название: Re: Использование чистой виртуальной функции в конструкторе Отправлено: ctin от Июнь 07, 2013, 13:00 Добавлю от себя. Сталкивался с подобной проблемой, когда была куча диалоговых окон с различным функционалом, который задавался при инициализации.
Решил так: Код: { |