C/C++中獲取重載函數(shù)地址的方法
1.現(xiàn)象
函數(shù)重載在C/C++編碼中是非常常見的,但是我們在std::bind或std::function綁定函數(shù)地址的時候,直接取地址,程序編譯就會報錯,示例如下:
class CFunc12345 { public: void func12345(int x) { std::cout << x; } void func12345(double x) { std::cout << x; } }; void func67890(int x) { std::cout << x; } void func67890(double x) { std::cout << x; } int main() { CFunc12345 x1; auto p = std::bind(&CFunc12345::func12345, x1, std::placeholders::_1); //[1]編譯報錯 p(14124); auto p1 = std::bind(&func67890, std::placeholders::_1); //[2]編譯報錯 p1(33333333); std::function<void(int)> p2(&func67890); //[3]編譯報錯 p2(33333333); return 0; }
上述代碼[1],[2],[3]處都會出現(xiàn)編譯錯誤,那是因為函數(shù)重載,多個函數(shù)名相同,找不到該用那個函數(shù)地址。這個時候解決辦法就是人為指定用那個函數(shù),那么人為指定用那個函數(shù)有哪些辦法呢?
2.指定參數(shù)取函數(shù)地址
方法如下:
//方法1: CFunc12345 x1; using FUNC1 = void (CFunc12345::*)(int); FUNC1 func1 = &CFunc12345::func12345; auto p1 = std::bind(func1, x1, std::placeholders::_1); p1(14124); using FUNC2 = void(*)(int); FUNC2 func2 = &func67890; auto p2 = std::bind(func2, std::placeholders::_1); p2(14124); FUNC2 func3 = &func67890; std::function<void(int)> p3(func3); p3(14124);
從代碼可以看出,就是手動指定函數(shù)類型,先取到函數(shù)地址后,再把地址傳入指定的對象(如std::bind、std::function等)中,避免了std::bind或std::function去判斷函數(shù)類型,從而避免了編譯錯誤。
3.利用Qt的類QOverload
QOverload是Qt5中提供的一種用于重載信號和槽函數(shù)連接的方式。它允許開發(fā)者在使用信號與槽機制時,更靈活地處理函數(shù)重載的情況。通過將信號和槽函數(shù)的參數(shù)類型轉(zhuǎn)換為指定類型,QOverload實現(xiàn)了對信號和槽函數(shù)的類型安全檢查。
在實際應(yīng)用中,QOverload通過重載調(diào)用QOverload::of,利用它來指定多個信號版本中的具體哪種類型參數(shù)。例如,當(dāng)有一個信號函數(shù)被重載,具有多個不同參數(shù)類型的版本時,可以使用QOverload來明確指定要連接的是哪個版本的信號函數(shù)。
QOverload的作用就是指定重載函數(shù)中的函數(shù)類型,從它的源碼中可以看出來,源碼如下:
template <typename... Args> struct QNonConstOverload { template <typename R, typename T> Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) { return ptr; } template <typename R, typename T> static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) { return ptr; } }; template <typename... Args> struct QConstOverload { template <typename R, typename T> Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr) { return ptr; } template <typename R, typename T> static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr) { return ptr; } }; template <typename... Args> struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...> { using QConstOverload<Args...>::of; using QConstOverload<Args...>::operator(); using QNonConstOverload<Args...>::of; using QNonConstOverload<Args...>::operator(); template <typename R> Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) { return ptr; } template <typename R> static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) { return ptr; } };
顧名思義,模版類QNonConstOverload是取不帶const的類成員函數(shù)的地址的,模版類QConstOverload是取帶const的類成員函數(shù)的地址的,QOverload是取普通函數(shù)地址的,它們之間的關(guān)系如下圖所示:
于是上面編譯錯誤的代碼可以修改為:
int main() { //方法2 CFunc12345 x1; auto p = std::bind(QOverload<int>::of(&CFunc12345::func12345), x1, std::placeholders::_1); p(14124); auto p1 = std::bind(QOverload<int>::of(&func67890), std::placeholders::_1); p1(33333333); std::function<void(int)> p2(QOverload<int>::of(&func67890)); p2(33333333); return 0; }
QOverload看似只有裝有Qt環(huán)境才能用,其實把源碼稍加修改就可以作為標(biāo)準(zhǔn)的C++類來用,修改后的COverload源碼如下所示:
template <typename... Args> struct CNonConstOverload { template <typename R, typename T> auto operator()(R(T::* ptr)(Args...)) const -> decltype(ptr) { return ptr; } template <typename R, typename T> static auto of(R(T::* ptr)(Args...)) -> decltype(ptr) { return ptr; } }; template <typename... Args> struct CConstOverload { template <typename R, typename T> auto operator()(R(T::* ptr)(Args...) const) const -> decltype(ptr) { return ptr; } template <typename R, typename T> static auto of(R(T::* ptr)(Args...) const) -> decltype(ptr) { return ptr; } }; template <typename... Args> struct COverload : CConstOverload<Args...>, CNonConstOverload<Args...> { using CConstOverload<Args...>::of; using CConstOverload<Args...>::operator(); using CNonConstOverload<Args...>::of; using CNonConstOverload<Args...>::operator(); template <typename R> auto operator()(R(*ptr)(Args...)) const -> decltype(ptr) { return ptr; } template <typename R> static auto of(R(*ptr)(Args...)) -> decltype(ptr) { return ptr; } };
QOverload在Qt的信號槽中也用的比較多。信號槽連接時,使用基于字符串的語法,可以顯式指定參數(shù)類型。因此,使用重載信號或槽的哪一個實例是明確的。相反,使用基于模版函數(shù)的語法,必須強制轉(zhuǎn)換重載信號或槽,以告訴編譯器要使用哪個實例。
例如,QLCDNumber有三個版本的display() 槽函數(shù):
1.QLCDNumber::display(int)
2.QLCDNumber::display(double)
3.QLCDNumber::display(QString)
使用信號QSlider::valueChanged()和QLCDNumber::display(int)連接,可以有如下系列方法:
auto slider = new QSlider(this); auto lcd = new QLCDNumber(this); // String-based syntax connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int))); // Functor-based syntax, first alternative connect(slider, &QSlider::valueChanged, lcd, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display)); // Functor-based syntax, second alternative void (QLCDNumber::*mySlot)(int) = &QLCDNumber::display; connect(slider, &QSlider::valueChanged, lcd, mySlot); // Functor-based syntax, third alternative connect(slider, &QSlider::valueChanged, lcd, QOverload<int>::of(&QLCDNumber::display)); // Functor-based syntax, fourth alternative (requires C++14) connect(slider, &QSlider::valueChanged, lcd, qOverload<int>(&QLCDNumber::display));
總的來說,QOverload是一個強大的工具,它使得在Qt中使用信號和槽機制時,處理函數(shù)重載的情況變得更加簡單和直觀。
以上就是C/C++中重載函數(shù)取地址的方法的詳細(xì)內(nèi)容,更多關(guān)于C/C++重載函數(shù)取地址的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解C語言中strcpy()函數(shù)與strncpy()函數(shù)的使用
這篇文章主要介紹了詳解C語言中strcpy()函數(shù)與strncpy()函數(shù)的使用,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-08-08cocos2dx實現(xiàn)橡皮擦效果以及判斷是否擦除完畢
這篇文章主要為大家詳細(xì)介紹了cocos2dx實現(xiàn)橡皮擦效果以及判斷是否擦除完畢,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12c++標(biāo)準(zhǔn)輸入輸出流關(guān)系的前世今生
這篇文章主要給大家介紹了關(guān)于c++標(biāo)準(zhǔn)輸入輸出流關(guān)系的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04深入Windows下的回車是回車換行(\r\n)還是換行回車(\n\r)的詳解
本篇文章對Windows下的回車是回車換行(\r\n)還是換行回車(\n\r)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05