![](/img/trans.png)
[英]Using C++, how to call a base class method from a derived class method and apply this to an object passed as an argument?
[英]C++ call method passed as argument
我有一個Session類,定義了多個采用不同參數的Send方法。 例如:
class Session
{
public:
void SendInt(int i);
void SendTwoInts(int i1, int i2);
void SendStringAndInt(const std::string& str, int i);
};
我也擁有保存所有會話的SessionsManager類。
class SessionsManager
{
private:
std::vector<Session*> m_Sessions;
...
};
我想向每個會話調用相同方法的SessionsManager類添加廣播方法。 如果我僅為每個會話發送方法定義一個單獨的廣播方法,我將結束:
class SessionsManager
{
public:
void BroadcastInt(int i) { for(auto it : m_Sessions) { it->SendInt(i); } };
void BroadcastTwoInts(int i1, int i2) { for(auto it : m_Sessions) { it->SendTwoInts(i1, i2); } };
...
};
復制粘貼太多,理論上,Send方法的數量在將來會增加。 我想要更聰明的東西。
在理想的情況下,我設想有一個模板化的Broadcast方法,該方法將Session方法及其參數作為參數,例如:
template<typename Method, typename ...Args)
void Broadcast(Method, Args ... args)
{
...
}
廣播呼叫將是
Broadcast(&Session::SendInt, 2);
Broadcast(&Session::SendTwoInts, 2, 3);
問題是我不確定是否有可能以及如何准確實現廣播。 我在考慮std :: function和std :: bind,但是仍然無法編譯我的代碼。
任何想法都歡迎。
可能有2個具有相同參數但語義不同的Send方法。 例如:
void SendName(const std::string& name);
void SendDescription(const std::string& description);
老實說,我將通過使用一個用於Broadcast
的可變參數模板來解決此問題,並簡單地為不同的參數重載Send()
方法。
這是代碼:
#include <vector>
#include <string>
class Session
{
public:
void Send(int i) { }
void Send(int i1, int i2) { }
void Send(const std::string& str, int i) { }
};
class SessionsManager
{
public:
template<typename... Args>
void Broadcast(Args&&... args)
{
for(auto it : m_Sessions)
{
it->Send(std::forward<Args>(args)...);
}
}
private:
std::vector<Session*> m_Sessions;
};
這是您將如何使用它:
int main()
{
SessionsManager sm;
sm.Broadcast(1, 2);
sm.Broadcast(1);
sm.Broadcast("Hello", 2);
}
這是一個生動的例子 。
更新:
如果您真的負擔不起過載,那么此解決方案可以滿足您的原始要求:
#include <vector>
#include <string>
class Session
{
public:
void SendInt(int i) { }
void SendTwoInts(int i1, int i2) { }
void SendStringAndInt(const std::string& str, int i) { }
};
class SessionsManager
{
public:
template<typename M, typename... Args>
void Broadcast(M m, Args&&... args)
{
for(auto it : m_Sessions)
{
((*it).*m)(std::forward<Args>(args)...);
}
}
private:
std::vector<Session*> m_Sessions; // You could use shared_ptr<> here
};
這是您將如何使用它:
int main()
{
SessionsManager sm;
sm.Broadcast(&Session::SendTwoInts, 1, 2);
sm.Broadcast(&Session::SendInt, 1);
sm.Broadcast(&Session::SendStringAndInt, "Hello", 1);
}
這是一個生動的例子 。
使用std::bind
解決方案可能看起來像
#include <iostream>
#include <functional>
#include <vector>
class Session
{
public:
void SendInt(int i){ std::cout << i; }
void SendTwoInts(int i1, int i2){ std::cout << i1;}
};
class SessionsManager
{
public:
std::vector<Session*> m_Sessions;
template<typename T, typename ...Args>
void Broadcast(T f, Args&& ...args) {
for (auto it : m_Sessions) {
std::bind(f, it, std::forward<Args>(args)...)();
}
}
};
int main() {
SessionsManager m;
m.m_Sessions.push_back(new Session());
m.m_Sessions.push_back(new Session());
m.Broadcast(&Session::SendInt, 2);
m.Broadcast(&Session::SendTwoInts, 3, 2);
}
我不知道您到底要達到什么目標。 看起來one SessionsManager have multiple Sessions
。 在SessionManager
上執行操作會將該操作中繼到其所有Session
並且您有一個將命令發送到SessionManager
的廣播SessionManager
struct SessionManager{
template <typename F>
void broadcast(F f){
std::for_each(m_sessions.begin(), m_sessions.end(), f);
}
std::vector<Session*> m_sessions;
};
現在,您進行boost::bind
並將其發送到SessionManager::broadcast
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.