136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
1

Переопределение метода класса-шаблона

04.09.2014, 21:57. Показов 4209. Ответов 20
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Привет народ. Есть такой код:
C++
1
2
3
4
5
6
typedef OS::process<OS::pr0, 90> TProc1;
TProc1 Proc1;
template<> void Proc1::exec()
{
    //тут кот
}
Можете объяснить как это работает? А если точнее, зачем при переопределении функции класса proc писать tamplate<>? И, я правильно понимаю - здесь есть класс proc, в нем виртуальный метод exec(). Класс построен на шаблоне - в нем указывается два параметра, в данном случае это приоритет и размер стека. Мы для удобства делаем typedef, чтобы обозвать данный набор параметров, а потом создаем объект класса, которому переопределяем метод exec(). Я всё правильно понимаю?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.09.2014, 21:57
Ответы с готовыми решениями:

Определение метода-шаблона за пределами шаблона класса
День добрый! Разбираюсь в шаблонах, решил копнуть поглубже. Вот пример: template &lt;typename T1&gt;...

Синтаксис определения метода специализии шаблона класса.
Есть некий шаблон класса: template &lt;typename T1, typename T2, typename T3&gt; class А { }; Есть...

Вынос реализации метода шаблона класса в другой файл
Здравствуйте! Допустим, есть класс: // class.hpp #ifndef CLASS_HPP_ #define CLASS_HPP_ ...

Передача метода класса в качестве параметра для метода другого класса
Здравствуйте, Передо мной стоит такая задача. Необходимо разработать механизм, который бы мог...

20
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
04.09.2014, 22:16 2
Вообще-то, тут что-то не логичное. TProc1 - синоним типа OS::process<OS::pr0, 90>. Proc1 - стало быть экземпляр этого типа. И третья строка совсем этим не стыкуется. То же самое, что написать:
C++
1
2
SomeClass a;
a::f(){} // Должен быть тип, а не экземпляр класса
0
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
04.09.2014, 22:21  [ТС] 3
Тем не менее - это строчка из примера для запуска процесса операционки scmRTOS (для микроконтроллеров, но C++ он и в Африке).
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
04.09.2014, 22:28 4
NoobsEnslaver, ссылку на пример можно увидеть?
0
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
04.09.2014, 22:38  [ТС] 5
Вот ссылка на sourceforge:
http://sourceforge.net/project... r/download
Там зайти в AVR\GCC\MEGA\3-Channel\main.c
Или вот, именно кусочек того что тебе нужно, чтобы не рыться:
https://cloud.mail.ru/public/8... %2FMEGA.7z
0
Модератор
Эксперт JS
5197 / 2079 / 406
Регистрация: 06.01.2013
Сообщений: 4,793
04.09.2014, 22:59 6
NoobsEnslaver, либо ссылка не та, либо что-то совсем странное. Ибо я вижу только пример с Тип::метод
0
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
04.09.2014, 23:35  [ТС] 7
Ну как же, точно 3-Channel\src\main.c смотрел?
Вот оттуда фрагменты:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
//      Process types
//
typedef OS::process<OS::pr0, 120> TProc1;
typedef OS::process<OS::pr1, 160> TProc2;
typedef OS::process<OS::pr2, 120> TProc3;
 
//---------------------------------------------------------------------------
//
//      Process objects
TProc1 Proc1;
TProc2 Proc2;
TProc3 Proc3;
...
template<> void TProc1::exec()
{
    DRIVER(PROC1,OUT);
    DRIVER(TIMER1_TO_PROC1,OUT);
    for(;;)
    {
        OFF(PROC1);
        Timer1_Ovf.Wait();
        ON(PROC1);
        OFF(TIMER1_TO_PROC1);
        SlonQueue.push(&African);
    }
} // TProc1::exec()
 
} // namespace OS
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
04.09.2014, 23:57 8
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
Вот оттуда фрагменты:
Сравним. Первый пост:
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
C++
1
2
template<> void Proc1::exec()
{
7 пост:
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
C++
1
2
template<> void TProc1::exec()
{
0
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
05.09.2014, 00:02  [ТС] 9
Да да да... недосмотрел я эту Т Спасибо) Ну ладно, а дальше по сабжу - я правильно истолковал, кроме момента с потерянной "Т" код? И еще - зачем при переопределении exec() вначале ставится template<>? Не совсем понимаю этот механизм..
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
05.09.2014, 01:42 10
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
И еще - зачем при переопределении exec() вначале ставится template<>? Не совсем понимаю этот механизм..
Затем, что OS:: process - это шаблон.
А
C++
1
template<> void TProc1::exec()
можно переписать так:
C++
1
template<> OS::process<OS::pr0, 120>::exec()
Это явная специализация (явное инстанцирование) метода шаблонного класса. Используется для повышения эффективности кодогенерации (иначе такая функция будет генерироваться в каждой единице трансляции, где инстанцируется шаблон). Обрати внимание, что в заголовочном файле специально оставлено только определение этого метода. Если мы попытаемся инстанцировать OS:: process какими-то другими аргументами, отличными от явно специализированных, то получим ошибку линковщика.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.09.2014, 02:00 11
Цитата Сообщение от DrOffset Посмотреть сообщение
явное инстанцирование
А разве у явного инстанцирования такой синтаксис?
Миниатюры
Переопределение метода класса-шаблона  
0
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
05.09.2014, 09:06  [ТС] 12
Всётаки еще не понятно - во-первых почему вначале мы ставим template<>, хотя дальше у нас и так идет конкретизация шаблона <OS:r0, 120>, во-вторых - не возникнет проблем из за того, что мы сначала создали объект класса, а потом переопределили ему метод? И в-третьих, ну эт немного по-нубски, но всёже - разве создание объекта класса происходит не так
C++
1
TProc1 Proc1 = new TProc();
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
05.09.2014, 10:32 13
Лучший ответ Сообщение было отмечено NoobsEnslaver как решение

Решение

Цитата Сообщение от alsav22 Посмотреть сообщение
А разве у явного инстанцирования такой синтаксис?
Это специализация функции шаблона. Явное инстанцирование тут происходит вследствие нее.
Явно инстанцировать такой метод можно несколькими способами.
Первый способ написать явное инстанцирование для всего класса
C++
1
2
3
4
5
6
7
8
template <typename T1, typename T2>
class A
{
public:
    void foo();
};
 
template class A<int, int>; // explicit istantiation
Можно также инстанцировать конкретную функцию
C++
1
template void A<int, int>::foo();
но для того, чтобы это работало, должно быть доступно определение этого шаблонного метода
C++
1
2
3
4
template <typename T1, typename T2>
void A<T1, T2>::foo()
{
}
причем, если мы напишем
C++
1
2
3
template void A<int, int>::foo();
template void A<int, double>::foo();
template void A<int, short>::foo();
то он сгенерирует три функции, но по одному шаблону. В примере ТС ситуация другая: нужно явное инстанцирование для разных реализаций exec.
Поэтому мы воспользовались специализией (но явное инстанцирование от этого не перестало происходить).
C++
1
2
3
4
template <>
void A<int, int>::foo()
{
}
Отвечая на вопрос ТС, зачем там скобочки: такой синтаксис принят, чтобы обозначить, что это полная специализация. Потому что может быть еще и частичная (которая не приводит к явному инстанцированию, поэтому для нее должен быть доступен и частично специализированный шаблон):
C++
1
2
3
4
5
6
7
8
9
10
11
template <typename T>
class A<T, int>
{
public:
    void foo();
};
 
template <typename T>
void A<T, int>::foo()
{
}
Добавлено через 4 минуты
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
не возникнет проблем из за того, что мы сначала создали объект класса, а потом переопределили ему метод?
Вот такая запись же тебя не смущает:
C++
1
2
3
4
5
6
7
8
9
10
void foo();
 
int main()
{
    foo();
}
 
void foo()
{
}
Так почему в рассматриваемом случае должно?
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
разве создание объекта класса происходит не так
Ты привел пример создания объекта в куче (heap). Это не единственный способ.
4
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
06.09.2014, 01:13 14
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
И в-третьих, ну эт немного по-нубски, но всёже - разве создание объекта класса происходит не так
C++
1
TProc1 Proc1 = new TProc();
C++
1
2
TProc1* Proc1 = new TProc(); // объект создаётся в динамической памяти (куче), возвращается указатель на эту память.
TProc1 Proc1; // объект создаётся в автоматической памяти (на стеке)
Добавлено через 11 часов 32 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
Поэтому мы воспользовались специализией (но явное инстанцирование от этого не перестало происходить).
DrOffset, я правильно понял, что явное инстанцирование функции происходит тогда, когда компилятор встречает именно определение явной специализации, а не объявление (в отличие от такого явного инстанцирования:
C++
1
template void A<int, int>::foo();
)?
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
06.09.2014, 01:29 15
Цитата Сообщение от alsav22 Посмотреть сообщение
в отличие от такого явного инстанцирования
Такое инстанцирование всегда требует наличие доступного определения в данной единице трансляции (без него оно не должно компилироваться). Поэтому чисто технически нет никакой разницы. Разница в примере ТС в том, что мы явно инстанцировали три разные версии функций (в смысле с разным телом), использовав явную специализацию функции. В отличие от инстанцирования трех одинаковых (в смысле по одному и тому же шаблону) функций, в случае использования такого синтаксиса:
C++
1
2
3
template void A<int, int>::foo();
template void A<int, short>::foo();
template void A<int, char>::foo();
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
06.09.2014, 01:48 16
Цитата Сообщение от DrOffset Посмотреть сообщение
без него оно не должно компилироваться
Компилируется, но экземпляр шаблона, как я понял, не создаётся (студия 10).
Цитата Сообщение от DrOffset Посмотреть сообщение
Такое инстанцирование всегда требует наличие доступного определения в данной единице трансляции
И то и другое требует этого. Но:
Цитата Сообщение от alsav22 Посмотреть сообщение
я правильно понял, что явное инстанцирование функции происходит тогда, когда компилятор встречает именно определение явной специализации, а не объявление?
Добавлено через 5 минут
Я почему прицепился: подумал, что в 10 посте приведены объявления специализаций, и написано:
Цитата Сообщение от DrOffset Посмотреть сообщение
Это явная специализация (явное инстанцирование) метода шаблонного класса
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
06.09.2014, 02:05 17
Цитата Сообщение от alsav22 Посмотреть сообщение
подумал, что в 10 посте приведены объявления специализаций, и написано:
Объявление и определение - это не одно и то же.
Объявление там в основном шаблоне, вынесено в h-файл. Определения там три, для каждой специализации. Но т.к. специализация явная, то она приводит к инстацированию (генерации) функций. Я специально указал сперва синтаксическое определение, а затем в скобочках эффект, который при этом достигается. Этого собственно и добивался автор. Вызов метода exec из другой единицы трансляции не будет приводить к инстацированию, вместо этого будут использованы уже инстацированные функции из модуля, который мы тут рассматривали.
Я понимаю, что тебя сбило с толку не "книжное" изложение материала. Но это не расходится с теорией, т.к. механизмы все взаимосвязаны и здесь важно понимать что именно происходит при тех или иных действиях, а не просто запоминать и ассоциировать поведение с определенным синтаксисом.

Добавлено через 5 минут
Цитата Сообщение от alsav22 Посмотреть сообщение
Компилируется, но экземпляр шаблона, как я понял, не создаётся (студия 10).
Да, сейчас попробовал в 2012 студии, выдал только warning:
warning C4661: void A<T1,T2>::foo(void): отсутствует подходящее определение для запроса на явное создание экземпляра шаблона
Цитата Сообщение от alsav22 Посмотреть сообщение
явное инстанцирование функции происходит тогда, когда компилятор встречает именно определение явной специализации, а не объявление?
Да.
1
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
06.09.2014, 02:13 18
Цитата Сообщение от DrOffset Посмотреть сообщение
Объявление и определение - это не одно и то же.
Объявление там в основном шаблоне, вынесено в h-файл.
Нет. Там в main.cpp объявления специализаций прописаны:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//---------------------------------------------------------------------------
//
//      Process types
//
typedef OS::process<OS::pr0, 120> TProc1;
typedef OS::process<OS::pr1, 160> TProc2;
typedef OS::process<OS::pr2, 120> TProc3;
 
// Explicit specialization of function must precede its first use. But ...
// avoid GCC bug ( [url]http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15867[/url] )
#if 0
    template<> void TProc1::exec();
    template<> void TProc2::exec();
    template<> void TProc3::exec();
#endif
Добавлено через 7 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
Я понимаю, что тебя сбило с толку не "книжное" изложение материала.
Нет, меня сбило то, что я неправильно понял код из 10 поста, подумал, что там приведено объявление специализаци,
и дальше написано:
Цитата Сообщение от DrOffset Посмотреть сообщение
Это ... явное инстанцирование
, что не так, так как:
Цитата Сообщение от DrOffset Посмотреть сообщение
Сообщение от alsav22 явное инстанцирование функции происходит тогда, когда компилятор встречает именно определение явной специализации, а не объявление?

Да.
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
06.09.2014, 02:21 19
Цитата Сообщение от alsav22 Посмотреть сообщение
Нет. Там в main.cpp объявления специализаций прописаны:
typedef - Это не объявления.
Или ты про то, что в #if 0?

Добавлено через 3 минуты
Цитата Сообщение от alsav22 Посмотреть сообщение
что не так, так как:
Это еще почему? Что-то от тебя ускользнула похоже мысль.
Определение явной специализации, вот оно:
C++
1
2
3
4
5
template <>
void A<int, int>::foo()
{
   //...
}
И тут же явное инстацирование.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
06.09.2014, 02:25 20
Цитата Сообщение от DrOffset Посмотреть сообщение
Или ты про то, что в #if 0?
Да.

Добавлено через 3 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
Что-то от тебя ускользнула похоже мысль.
DrOffset, это от тебя моя мысль ускальзывает.
Давай так. Если было бы вот так написано, это было бы правильно?
C++
1
template<> OS::process<OS::pr0, 120>::exec(); // Здесь происходит явное инстанцирование метода шаблонного класса.
0
06.09.2014, 02:25
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.09.2014, 02:25
Помогаю со студенческими работами здесь

Переопределение виртуального метода
Нужно написать виртуальный метод в родительском классе , который находит площадь круга. Затем...

Наследование. Переопределение метода родителя
не работает конструкция вида: class AllFigureData { protected: int id; int x; int y;...

Вызов метода класса из метода другого класса
Помогите школнегу Имеется несколько классов class Com { protected: unsigned char bufrd,...

Явное создание экземпляра класса и явная специализация шаблона класса
Всем добрый день! Не могу разобраться - эти две технологии дают один и тот же результат? В каких...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru