Важное замечание: Этот вопрос становится довольно длинным, если вы читаете его впервые, я предлагаю вам начать с нижней части, так как решение в подходе, но код немного вонючий.
Прочитав учебник по шаблонам , я смог изменить свой существующий класс для поддержки универсальных типов. Однако многие объекты уже зависят от этого, поэтому я ищу способ сделать метод универсальным, а не весь класс.
Я пробовал следующее, но похоже, что это поведение не поддерживается.
// foobar1.h
// Don't want the entire class to be generic.
//template<class T>
class FooBar1
{
public:
template<class T> T Foo();
}
// foobar2.h
class FooBar2 : public FooBar1
{
}
// foobar1.cpp
template<class T>
T FooBar1::Foo()
{
return something;
}
// test.cpp
FooBar1 fb1;
FooBar2 fb2 = fb1.Foo<FooBar2>();
Это должно не сработать, или это ошибка в другом месте, с которой я запутался?
неопределенная ссылка на FooBar2 Foo<FooBar2>()
Чтобы представить это в какой-то перспективе относительно того, чего я хочу достичь, вот как я это сделаю в C # ...
public class FooBar1
{
public T Foo<T>()
where T : FooBar1
{
return something;
}
}
public class FooBar2 : FooBar1 { }
FooBar1 fb1 = new FooBar1();
FooBar2 fb2 = fb1.Foo<FooBar2>();
Есть ли способ сделать что-то подобное в C ++?
Обновление 1:
Просто исправил некоторые мелкие детали синтаксиса (я хотел сделать Foo общедоступным и вернуть T, а не FooBar2). По-прежнему получаю ошибку компилятора ... Когда я удаляю шаблон поведения, ошибка исчезает, ответ пока говорит, что я делаю правильно, но если это так, то почему я все еще получаю ошибку? Спасибо за ваши ответы!
Обновление 2:
Джош, вот фактический исходный код (ну, я думаю, что это актуально, да ладно, дайте мне знать, если вы считаете, что я пропустил важный бит).
// ImageMatrix.h
class ImageMatrix : public VImage
{
public:
// ... various functions ...
template<class T> T GetRotatedCopy(VDouble angle);
}
// ImageFilter.h
class ImageFilter : public ImageMatrix
{
// ... various functions ...
}
// ImageMatrix.cpp
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
// ... create a new instance of ImageMatrix and return it.
}
// ImageProcessor.cpp
ImageFilter filter2 = filterPrototype.GetRotatedCopy<ImageFilter>(90);
А вот фактическая ошибка компилятора:
/ home / nick / Projects / ViMRID / vimrid / Debug / libvimrid.so: неопределенная ссылка на `vimrid :: imaging :: processing :: ImageFilter vimrid :: imaging :: ImageMatrix :: GetRotatedCopy (double) '
Обновление 3:
Кстати, все, кроме строки реализации, находится в библиотеке; поэтому он вызывается из отдельного двоичного файла ... Имеет ли это значение? Исправление; все в одной библиотеке. Все блоки - это разные файлы.
Обновление 4:
Когда я закомментирую строку реализации (ImageFilter filter2 = filterPrototype ...), она будет работать нормально, так что, похоже, эта строка вызывает ее ...
Обновление 5 (решено?):
По-прежнему возникают проблемы ... Может ли это быть проблемой с пространствами имен? Поцарапайте это, хорошо, теперь я понял концепцию шаблонов! :) Определение шаблона должно быть в заголовке вместе с объявлением (верно?) - так что теперь, когда я переместил объявление в ImageMatrix.h
, все компилируется. Однако мне пришлось использовать dynamic_cast
, чтобы заставить его работать; это правильно? Если я далеко, поправьте меня!
// This is in the header file!
// Help!!! This looks really really smelly...
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
ImageMatrix image = _getRotatedCopy(angle);
ImageMatrix *imagePtr = ℑ
return *dynamic_cast<T*>(imagePtr);
}
Обновление 6:
Обращаясь к обновлению 5, когда я не использую dynamic_cast ...
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
ImageMatrix image = _getRotatedCopy(angle);
ImageMatrix *imagePtr = ℑ
//return *dynamic_cast<T*>(imagePtr);
return *imagePtr;
}
... Я получаю эту ошибку ...
../src/imaging/processing/../ImageMatrix.h: In member function ‘T vimrid::imaging::ImageMatrix::GetRotatedCopy(vimrid::VDouble) [with T = vimrid::imaging::processing::ImageFilter]’:
../src/imaging/processing/ImageProcessor.cpp:32: instantiated from here
../src/imaging/processing/../ImageMatrix.h:45: error: conversion from ‘vimrid::imaging::ImageMatrix’ to non-scalar type ‘vimrid::imaging::processing::ImageFilter’ requested
make: *** [src/imaging/processing/ImageProcessor.o] Error 1
Обновление 7:
Кроме того, если я не использую весь этот вонючий код в обновлении 6 ...
class ImageMatrix : public VImage
{
public:
template<class T> T GetRotatedCopy(VDouble angle);
private:
ImageMatrix _getRotatedCopy(VDouble angle);
};
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
return _getRotatedCopy(angle);
}
... Я получаю ту же ошибку, что и в обновлении 6.