Если я наследую от CBaseInterface (см. Код ниже) с шаблоном Argument T = int *, компилятор завершится ошибкой C2555. Это происходит со всеми типами указателей, используемых для T. Если я использую typedef вместо этого, тот же код работает нормально.
// If _FALIS is defined, the compiler fails, else it succeeds
// (MS Visual Studio 2013 Update 2, 32 and 64 Bit native C++, Debug build).
#define _FALIS
#ifdef _FALIS
#define PINT int*
#else
typedef int* PINT;
#endif
template <class T>
class CBaseInterface
{
public:
virtual ~CBaseInterface() {}
virtual const T Calculate() const = 0;
};
class CCalculator : public CBaseInterface<PINT>
{
public:
CCalculator() {}
virtual ~CCalculator() {}
// error C2555: 'CCalculator::Calculate':
// overriding virtual function return type differs and is not 'covariant'
// from 'CBaseInterface<int *>::Calculate'
virtual inline const PINT Calculate() const final
{
return (PINT)&m_Item;
}
protected:
int m_Item = 0;
};
Где проблема с типами указателей? Я в замешательстве и не нашел в документах Microsoft ничего такого, что бы соответствовало этой ситуации.
Надеюсь, ты сможешь мне помочь.
Разница заключается в значении const PINT
в производном классе.
Если PINT
является typedef для int *
, затем const PINT
является int * const
(постоянный указатель на изменяемый int) — это нормально, это то, для чего определена функция базового класса. Если вы используете свой макрос, то у вас есть буквально const int *
(изменяемый указатель на константу int), который является совершенно другим типом. Typedef логически подставляется в систему типов, макрос подставляется вслепую как токены.
Один из способов спасти это было бы написать PINT const
или же const (PINT)
(поэтому привязка const является явной).
И вы действительно не должны использовать макросы.