我試圖允許一個類實作一個介面,該介面被模板化以允許內部更新或不允許更新。如果實作在類宣告中,則代碼看起來像這樣并且可以作業。如果它被移出(如此處所示),我會在 Visual Studio 2019 上收到編譯器錯誤,我不明白為什么。感謝所有幫助!
以下代碼將無法編譯。如果將類外實作和標頭修改為僅使用我注釋掉的代碼,它會按預期編譯和作業。
#include <atomic>
#include <cstdint>
#include <memory>
#include <iostream>
#include <string>
enum class EntryType { Read, ReadUpdate };
template <EntryType Type>
class IXQ
{
public:
virtual float GetValue() = 0;
};
class X : public IXQ<EntryType::Read>, public IXQ<EntryType::ReadUpdate>
{
public:
float IXQ<EntryType::Read>::GetValue();
/*
float IXQ<EntryType::Read>::GetValue()
{
return _x;
}
*/
float IXQ<EntryType::ReadUpdate>::GetValue();
/*
float IXQ<EntryType::ReadUpdate>::GetValue() {
_counter ;
return _x;
}
*/
float _x = 10.0F;
std::atomic<std::int32_t> _counter = 0;
};
float X::IXQ<EntryType::Read>::GetValue()
{
return _x;
}
float X::IXQ<EntryType::ReadUpdate>::GetValue()
{
_counter ;
return _x;
};
int main(int argc, char* argv[])
{
{
auto k = std::make_unique<X>();
auto ptrQ = static_cast<IXQ<EntryType::Read>*>(k.get());
std::cout << std::to_string(ptrQ->GetValue()) << std::endl;
std::cout << k->_counter.load() << std::endl;
}
{
auto k = std::make_unique<X>();
auto ptrQ = static_cast<IXQ<EntryType::ReadUpdate>*>(k.get());
std::cout << std::to_string(ptrQ->GetValue()) << std::endl;
std::cout << k->_counter.load() << std::endl;
}
return 0;
}
uj5u.com熱心網友回復:
我認為這可以通過添加一個類的中間層來解決,假設可以X_Read從中繼承。X_ReadUpdateX
IXQ
/ \
X_Read X_ReadUpdate
\ /
X
訣竅是IXQ::GetValue通過呼叫兩個虛擬純方法來使用這些類來實作,比如說GetValueRead和GetValueReadUpdate。這樣,X仍然繼承自IXQ<EntryType::Read>and IXQ<EntryType::ReadUpdate>,但實作了GetValueReadand GetValueReadUpdate,這兩個方法具有清晰和不同的介面。
[演示]
template <EntryType Type>
class IXQ
{
public:
virtual float GetValue() = 0;
};
class X_Read : public IXQ<EntryType::Read>
{
public:
virtual float GetValue() override { return GetValueRead(); };
virtual float GetValueRead() = 0;
};
class X_ReadUpdate : public IXQ<EntryType::ReadUpdate>
{
public:
virtual float GetValue() override { return GetValueReadUpdate(); };
virtual float GetValueReadUpdate() = 0;
};
class X : public X_Read, public X_ReadUpdate
{
public:
virtual float GetValueRead() override { return _x; }
virtual float GetValueReadUpdate() { _counter ; return _x; };
float _x{10.0f};
std::atomic<std::int32_t> _counter{};
};
// Outputs:
// 10.000000
// 0
// 10.000000
// 1
uj5u.com熱心網友回復:
您用來覆寫的語法GetValue()不是標準的c 。
class X : public IXQ<EntryType::Read> {
public:
float IXQ<EntryType::Read>::GetValue() { /* ... */ }
}
這是一個 Microsoft 特定的 C 擴展,稱為顯式覆寫 (C ),旨在與__interfaces 一起使用(也是 Microsoft 特定的 c 擴展)。
__interfaces 不正式支持 c 模板,因為它們主要用于 COM 介面,例如:
[ object, uuid("00000000-0000-0000-0000-000000000001"), library_block ]
__interface ISomething {
// properties
[ id(0) ] int iInt;
[ id(5) ] BSTR bStr;
// functions
void DoSomething();
};
令人驚訝的是,它float IXQ<EntryType::Read>::GetValue() { /* ... */ }完全有效。
在標準 C 中,被覆寫的函式僅由名稱和引數決定,因此您唯一的選擇是同時覆寫它們。
例如:
class X : public IXQ<EntryType::Read>, public IXQ<EntryType::ReadUpdate>
{
public:
// will be the implementation for both IXQ<EntryType::Read> & IXQ<EntryType::ReadUpdate>
float GetValue() override;
};
float X::GetValue() {
/* ... */
}
另一種符合標準的方法是創建 2 個從給定介面繼承的類,然后讓 X 從它們兩個繼承:
class XRead : public IXQ<EntryType::Read> {
float GetValue() override { /* ... */ }
};
class XReadUpdate : public IXQ<EntryType::ReadUpdate> {
float GetValue() override { /* ... */ }
};
class X : public XRead, public XReadUpdate {
/* ... */
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/415737.html
標籤:
上一篇:如何在wso2apim中卷曲Publisherurl?
下一篇:如何將模板引數限制為僅浮點型別
