[英]C++ Extension functions?
是否有像C#中的C ++擴展?
例如在C#中你可以這樣做:
public static uint SwapEndian(this uint value)
{
var tmp = BitConverter.GetBytes(value);
Array.Reverse(tmp);
return BitConverter.ToUInt32(tmp, 0);
}
someuint.SwapEndian();
在C ++中有類似的東西嗎?
擴展方法(以及“靜態類”)只存在於C#/ Java語言中,因為設計者認為(Java方式)OOP是The One True Way,並且所有內容都必須是來自類的方法:
這不是C ++的做事方式。 在C ++中,您有名稱空間,自由函數和Koenig查找來擴展類的行為:
namespace foo
{
struct bar { ... };
void act_on_bar(const bar& b) { ... };
}
...
foo::bar b;
act_on_bar(b); // No need to qualify because of Koenig lookup
我通常認為擴展方法有害。 如果你對一個類附加太多的行為,你可能無法捕獲該類存在的原因。 另外(如“部分類”),它們傾向於使代碼與非本地類相關。 這很糟糕。
至於你的問題,在C ++中你只需:
template <typename T>
T swap_endian(T x)
{
union { T value; char bytes[sizeof(T)]; } u;
u.value = x;
for (size_t i = 0; i < sizeof(T)/2; i++)
swap(u.bytes[i], u.bytes[sizeof(T) - i - 1]);
return u.value;
}
用法:
swap_endian<std::uint32_t>(42);
或者,如果可以推斷出類型:
std::uint64_t x = 42;
std::uint64_t y = swap_endian(x);
C ++中沒有擴展函數。 您可以將它們定義為自由函數。
uint SwapEndian(uint value){ ... }
不是那樣,但你可以編寫運算符重載,這些重載可以處理你沒有編寫的類,它有點像方法擴展(但不適用於命名函數,只適用於那些尚未被該類定義的運算符)。 經典的例子是讓你的課程與cout
工作:
class MyClass {
public:
MyClass(const char* blah) : str(blah) { }
const char* string() const {
return str;
}
private:
const char* str;
};
// this is kinda like a method extension
ostream& operator<<(ostream& lhs, const MyClass& rhs) {
lhs << rhs.string();
}
// then you can use it like this
MyClass m("hey ho");
cout << m;
// prints hey ho
這當然是一個微不足道的例子,但你明白了。
不是以直接類似的方式,但很多時候您可以使用模板實現所需的效果。 如果不從原始類派生,則不能在C ++中將具體類“添加”到具體類,但您可以創建適用於任何類型的函數模板。
例如,這是一個函數模板庫,用於執行任何整數類型的ntoh類型轉換:
template<class Val> inline Val ntohx(const Val& in)
{
char out[sizeof(in)] = {0};
for( size_t i = 0; i < sizeof(Val); ++i )
out[i] = ((char*)&in)[sizeof(Val)-i-1];
return *(reinterpret_cast<Val*>(out));
}
template<> inline unsigned char ntohx<unsigned char>(const unsigned char & v )
{
return v;
}
template<> inline uint16_t ntohx<uint16_t>(const uint16_t & v)
{
return ntohs(v);
}
template<> inline uint32_t ntohx<uint32_t>(const uint32_t & v)
{
return ntohl(v);
}
template<> inline uint64_t ntohx<uint64_t>(const uint64_t & v)
{
uint32_t ret [] =
{
ntohl(((const uint32_t*)&v)[1]),
ntohl(((const uint32_t*)&v)[0])
};
return *((uint64_t*)&ret[0]);
}
template<> inline float ntohx<float>(const float& v)
{
uint32_t const* cast = reinterpret_cast<uint32_t const*>(&v);
uint32_t ret = ntohx(*cast);
return *(reinterpret_cast<float*>(&ret));
};
我發現的一種方法是使用帶有lambda表達式的重載“>>”運算符。 以下代碼演示了這一點。 您必須知道使用運算符“>>”而不是“ - >”,這是因為我使用的編譯器不允許運算符“ - >”重載。 另外,因為運算符“>>”的優先級低於“ - >”,所以必須使用括號強制編譯器按正確的順序計算等式。
最終,它成為您嘗試生成的代碼的樣式,可維護性,可靠性和清潔性的問題。 人們會爭辯定義“SubtractValue”方法,使用兩個參數創建更有效的代碼,但其他人會認為重載方法更易於維護。 最后,由建築師和開發人員決定對他們的項目重要的是什么。 我只是提供了一個可能的問題解決方案。
#include <functional>
#include <iostream>
#include <stdio.h>
#include <tchar.h>
// Some plain demo class that cannot be changed.
class DemoClass
{
public:
int GetValue() { return _value; }
int SetValue(int ivalue) { _value = ivalue; return _value; }
DemoClass *AddValue(int iadd) { this->_value += iadd; return this; }
private:
int _value = 0;
};
// Define Lambda expression type that takes and returns a reference to the object.
typedef std::function<DemoClass *(DemoClass *obj)> DemoClassExtension;
// Overload the ">>" operator because we cannot overload "->" to execute the extension.
DemoClass* operator>>(DemoClass *pobj, DemoClassExtension &method)
{
return method(pobj);
}
// Typical extensions.
// Subtract value "isub".
DemoClassExtension SubtractValue(int isub)
{
return [=](DemoClass *pobj) {
pobj->AddValue(-isub);
return pobj;
};
}
// Multiply value "imult".
DemoClassExtension MultiplyValue(int imult)
{
return [=](DemoClass *pobj) {
pobj->SetValue(pobj->GetValue() * imult);
return pobj;
};
}
int _tmain(int argc, _TCHAR* argv[])
{
DemoClass *pDemoObject = new DemoClass();
int value = (pDemoObject->AddValue(14) >> SubtractValue(4) >> MultiplyValue(2))->GetValue();
std::cout << "Value is " << value;
return 0;
}
上面的代碼輸出是“Value is 20”。
不,對不起,但在C ++中沒有類似的東西,它也永遠不會。 標准留下了許多依賴於實現的東西(即編譯器可以以任何方式執行它),並且C ++也沒有標准化的ABI 。
如果你指的是this
合格的方法參數,那么沒有。 但根據您的具體用例,可能會有一些其他聰明的技巧......您能提供更多細節嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.