[英]Overriding a virtual method in a base class with conditional type traits in derived template class
誰能解釋為什么下面的代碼在Visual Studio 2015 C ++中給出錯誤“錯誤C2259:'PropertyValue':無法實例化抽象類”?
編譯器是否無法識別派生類PropertyValue
中的條件指定函數ConvertToDevice()
具有相同的簽名?
非常感謝,
約翰
#include <type_traits>
#include <typeinfo>
class BasePropertyValue
{
public:
virtual int ConvertToDevice(void** ptrdObject) = 0;
};
template<typename T> class PropertyValue : public BasePropertyValue
{
public:
T value;
PropertyValue(T val)
{
value = val;
}
template<class Q = T>
typename std::enable_if<!std::is_pointer<Q>::value, int>::type ConvertToDevice(void** ptrdObject)
{
return 1;
}
template<class Q = T>
typename std::enable_if<std::is_pointer<Q>::value, int>::type ConvertToDevice(void** ptrdObject)
{
return 2;
}
};
void main()
{
PropertyValue<double>* prop1 = new PropertyValue<double>(20);
prop1->ConvertToDevice(nullptr);
double x = 20;
PropertyValue<double*>* prop2 = new PropertyValue<double*>(&x);
prop2->ConvertToDevice(nullptr);
return;
}
[edit]由於條件特征,這不是重復的問題。
首先,將要覆蓋的函數聲明為模板。 您不能具有模板虛擬功能。 就這么簡單。
對於該解決方案,您似乎已經制作了這些模板,只是為了能夠在兩個實現之間進行切換。 一個簡單的解決方案是實現覆蓋的單個函數,然后在其中調用模板函數:
template<typename T>
struct PropertyValue : BasePropertyValue {
T value;
// simpler constructor
PropertyValue(T val) : value{std::move(val)} {}
// the override keyword is important
int ConvertToDevice(void** ptrdObject) override
{
return ConvertToDeviceImpl(ptrdobject);
}
private:
template<class Q = T>
typename std::enable_if<!std::is_pointer<Q>::value, int>::type
ConvertToDeviceImpl(void** ptrdObject)
{
return 1;
}
template<class Q = T>
typename std::enable_if<std::is_pointer<Q>::value, int>::type
ConvertToDeviceImpl(void** ptrdObject)
{
return 2;
}
};
問題是
template<class Q = T>
typename std::enable_if<!std::is_pointer<Q>::value, int>::type ConvertToDevice(void** ptrdObject)
{
return 1;
}
是與基類中的純虛擬方法不匹配(也不覆蓋)的模板方法。
其他啟用SFINAE的功能也存在相同問題。
因此PropertyValue
仍然是純虛擬類,無法實例化。
一種可能的解決方案是創建一個中間基類,如下所示的midClass
class BasePropertyValue
{ public: virtual int ConvertToDevice (void ** ptrdObject) = 0; };
template <typename T, bool = std::is_pointer<T>::value>
class midClass;
template <typename T>
class midClass<T, false> : public BasePropertyValue
{ public: int ConvertToDevice (void ** ptrdObject) override { return 1; } };
template <typename T>
class midClass<T, true> : public BasePropertyValue
{ public: int ConvertToDevice (void ** ptrdObject) override { return 2; } };
template <typename T>
class PropertyValue : public midClass<T>
{
public:
T value;
PropertyValue (T val)
{ value = val; }
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.