Доступ к типу указателя функции базовых классов шаблона
-
21-08-2019 - |
Вопрос
У меня есть класс, который мне предоставили, и который я действительно не хочу менять, но хочу расширить.Я новичок в области шаблонов и шаблонов, экспериментирующий с шаблоном Decorator, примененным к классу шаблона.Класс шаблона содержит указатель на член (если я правильно понимаю семантику) еще в одном классе.Указатель на член — это десериализатор istream XML.Тип «T» — это тип XML-документа, который необходимо десериализовать.
template <typename T> class B {
public:
typedef std::auto_ptr<T> MYFUN(
std::istream&, const std::string&, const std::string& );
public:
B<T>( MYFUN* p );
private:
MYFUN *fptr;
std::string aString1;
std::string aString2;
};
Typedef кажется мне странным после прочтения http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5, и тем не менее этот класс, похоже, работает нормально как есть.В предоставленном заголовочном файле нет никаких дополнительных #defines, поэтому для меня это немного загадочно.
Теперь я пытаюсь расширить его как Decorator, потому что хочу немного больше поработать над объектом auto_ptr, возвращаемым MYFUN:
template <typename T>
class D : public class B<T>
{
D( B<T>::MYFUN *fPtr, B<T> *providedBase ); //compiler complaint
//Looks like B
private:
B* base_;
};
template <typename T>
D<T>::D( B<T>::MYFUN *p, B<T> *base ) //compiler complaint
:
B<T>::B( p ), base_(providedBase)
{ }
При попытке скомпилировать это, я получаю жалобу на синтаксис в двух показанных строках.Ошибка — это что-то вроде «ожидается ')' в *».Нет жалоб на то, что MYFUN не определен.
Когда я переопределяю указатель на член в D с той же сигнатурой, что и в D, т.е.
//change MYFUN to NEWFUN in D)
typedef std::auto_ptr<T> MYNEWFUN(
std::istream&, const std::string&, const std::string& );
Это работает.Я предпочитаю не делать этого с каждым D/декоратором, которого я могу сделать из B.Я попытался выполнить определение типа более глобально, но не смог получить правильный синтаксис из-за того, что параметр шаблона не определен.
Решение
Ошибка компиляции связана с тем, что компилятор не может определить, что вы говорите о типе.
Пытаться:
D( typename B<T>::MYFUN *fPtr, B<T> *providedBase );
и
template <typename T>
D<T>::D( typename B<T>::MYFUN *p, B<T> *base )
Видеть: раздел шаблонов C++ FAQ Lite подробнее о том, почему это необходимо, но суть в том, что из-за возможности специализации шаблона компилятор не может быть уверен, что B<T>::MYFUN
на самом деле относится к типу.
Другие советы
Определение typedef MYFUN в B выполняется с частной видимостью.D не сможет получить к нему доступ.Если вы измените его на защищенный или общедоступный, это будет работать?
template <typename T> class B {
protected:
typedef std::auto_ptr<T> MYFUN(
std::istream&, const std::string&, const std::string& );
...
};
Проблема, которую я вижу в этом, заключается в том, что B::MYFUN - это частный определение типа.
Следовательно, любой наследующий класс не может получить к нему доступ.
Измените это на:
template <typename T> class B
{
public:
typedef std::auto_ptr<T> MYFUN( std::istream&, const std::string&, const std::string& );
public:
B<T>( MYFUN* p );
private:
MYFUN *fptr;
std::string aString1;
std::string aString2;
};