在 类 之间共享成员函数
Sharing member functions between classes
我正在设计一个应用程序,它使用一个 class 管理 TCP 连接和一个管理 UI 元素。连接管理器接收消息字符串并对它们进行最少的处理以确定它们的类型。如果它们是已知类型,连接管理器会将字符串传递给 GUI 管理器,以便它可以相应地更新 UI 元素。
我的挑战是:如果我不想在 class 中包含头文件,我如何允许访问其他 class 的 public 函数?
例如:
//message_types.h
typedef void(*MessageHandlerPointer)(std::string);
enum MessageTypes { info_type, time_type, command_type, reply_type,
inside_type, update_type, NUM_TYPES };
/////////////////////////////////////////////////////////////////////////
//ConnectionManager.h
class ConnectionManager
{
string hostname;
string port;
int connection_fd;
string message_types[NUM_TYPES];
string partial_message;
void process_message(string message);
MessageHandlerPointer message_handlers[NUM_TYPES];
public:
ConnectionManager(string hostname, string port);
~ConnectionManager();
int connect();
void disconnect();
void listen();
};
/////////////////////////////////////////////////////////////////////////
//ConnectionManager.cpp
ConnectionManager::ConnectionManager(string hostname, string port,
void (*message_handlers[NUM_TYPES])(string)):
hostname(hostname), port(port),
message_types { "i", "t", "c", "r", "I", "u" }
{
for(int i = 0; i < NUM_TYPES; i++)
{
this->message_handlers[i] = message_handlers[i];
}
}
/////////////////////////////////////////////////////////////////////////
//GuiManager.h
class GuiManager
{
void info_handler(string msg);
void time_handler(string msg);
void command_handler(string msg);
void reply_handler(string msg);
void inside_handler(string msg);
void update_handler(string msg);
public:
GuiManager();
~GuiManager();
MessageHandlerPointer message_handlers[NUM_TYPES];
};
/////////////////////////////////////////////////////////////////////////
//GuiManager.cpp
GuiManager::GuiManager()
{
message_handlers[info_code] = &info_handler;
message_handlers[time_code] = &time_handler;
message_handlers[command_code] = &command_handler;
message_handlers[reply_code] = &reply_handler;
message_handlers[inside_code] = &inside_handler;
message_handlers[update_code] = &update_handler;
}
/////////////////////////////////////////////////////////////////////////
//generic main.cpp
int main()
{
GuiManager gm();
ConnectionManager cm("host", "45123", gm.message_handlers);
}
但 C++ 不希望我这样做,我隐约明白为什么。成员函数不是自由函数。但我希望我可以使这些功能有点所有者或 class 不可知论者?
不管怎样,我的想法不会让我达到我想去的地方,所以我很高兴听到其他人对最佳解决方案的看法。
此外,我认识到,为了模块化而不让 classes 直接相互交互,我可能会变得有点可笑。我是否错过了要点/为了原则而牺牲了简单性?
我对 OO 还很陌生,所以我对任何答案的所有细节都很感兴趣。 =)
因此,如果我没猜错,您希望 ConnectionManager 将消息转发到 GUIManager,但不必包含 GUIManager 的 header,只需使用前向声明即可。
你卡住的地方是当你注意到
的类型时
void GUIManager::handle_info( std::string )
这与指向自由函数的指针类型不同
void handle_info (std::string).
要声明指向前者的指针,您必须编写
typedef void (GUIManager::*MessageHandlerPointer)(string );
我写了一个简化的示例(使用 Foo 和 Bar :)),其中 Bar 的实例将消息转发给 Foo 的实例。这是:
#include <iostream>
#include <string>
using namespace std;
class Foo;
typedef void (Foo::*FooMessageHandlerPointer)(string ); // this is the type of a pointer to a member of Foo that gets a string and returns void.
class Bar
{
public:
Bar ( Foo* foo_, FooMessageHandlerPointer ptr )
:
foo (foo_),
p (ptr)
{}
public:
void ForwardMessage ( string s )
{
(foo->*p)(s);
}
private:
Foo* foo;
FooMessageHandlerPointer p;
};
class Foo
{
public:
void ProcessMessage (string s)
{
cout << "Foo received: " << s << "\n";
}
};
int main (void)
{
Foo foo1;
Bar bar1 ( &foo1, &Foo::ProcessMessage );
bar1.ForwardMessage( "Hello world!" );
return 0;
}
注意,在定义Bar时,它只有Foo的前向声明和成员函数指针的类型可用。
还要注意,Bar 不仅需要指向函数的指针,还需要指向实例的指针。当然,当您在 main 中创建 Bar 的实例时,您需要有权访问 headers.
希望我答对了你的问题,这对你有帮助。否则这是一个很好的练习,因为这些天我一直在玩指向成员函数的指针:)
更新:
在您发表评论之后,我认为您可能正在寻找类似委托的东西,它封装了要调用的函数,无论是自由函数还是成员函数。也许 this 话题会有所帮助
我正在设计一个应用程序,它使用一个 class 管理 TCP 连接和一个管理 UI 元素。连接管理器接收消息字符串并对它们进行最少的处理以确定它们的类型。如果它们是已知类型,连接管理器会将字符串传递给 GUI 管理器,以便它可以相应地更新 UI 元素。
我的挑战是:如果我不想在 class 中包含头文件,我如何允许访问其他 class 的 public 函数?
例如:
//message_types.h
typedef void(*MessageHandlerPointer)(std::string);
enum MessageTypes { info_type, time_type, command_type, reply_type,
inside_type, update_type, NUM_TYPES };
/////////////////////////////////////////////////////////////////////////
//ConnectionManager.h
class ConnectionManager
{
string hostname;
string port;
int connection_fd;
string message_types[NUM_TYPES];
string partial_message;
void process_message(string message);
MessageHandlerPointer message_handlers[NUM_TYPES];
public:
ConnectionManager(string hostname, string port);
~ConnectionManager();
int connect();
void disconnect();
void listen();
};
/////////////////////////////////////////////////////////////////////////
//ConnectionManager.cpp
ConnectionManager::ConnectionManager(string hostname, string port,
void (*message_handlers[NUM_TYPES])(string)):
hostname(hostname), port(port),
message_types { "i", "t", "c", "r", "I", "u" }
{
for(int i = 0; i < NUM_TYPES; i++)
{
this->message_handlers[i] = message_handlers[i];
}
}
/////////////////////////////////////////////////////////////////////////
//GuiManager.h
class GuiManager
{
void info_handler(string msg);
void time_handler(string msg);
void command_handler(string msg);
void reply_handler(string msg);
void inside_handler(string msg);
void update_handler(string msg);
public:
GuiManager();
~GuiManager();
MessageHandlerPointer message_handlers[NUM_TYPES];
};
/////////////////////////////////////////////////////////////////////////
//GuiManager.cpp
GuiManager::GuiManager()
{
message_handlers[info_code] = &info_handler;
message_handlers[time_code] = &time_handler;
message_handlers[command_code] = &command_handler;
message_handlers[reply_code] = &reply_handler;
message_handlers[inside_code] = &inside_handler;
message_handlers[update_code] = &update_handler;
}
/////////////////////////////////////////////////////////////////////////
//generic main.cpp
int main()
{
GuiManager gm();
ConnectionManager cm("host", "45123", gm.message_handlers);
}
但 C++ 不希望我这样做,我隐约明白为什么。成员函数不是自由函数。但我希望我可以使这些功能有点所有者或 class 不可知论者?
不管怎样,我的想法不会让我达到我想去的地方,所以我很高兴听到其他人对最佳解决方案的看法。
此外,我认识到,为了模块化而不让 classes 直接相互交互,我可能会变得有点可笑。我是否错过了要点/为了原则而牺牲了简单性?
我对 OO 还很陌生,所以我对任何答案的所有细节都很感兴趣。 =)
因此,如果我没猜错,您希望 ConnectionManager 将消息转发到 GUIManager,但不必包含 GUIManager 的 header,只需使用前向声明即可。
你卡住的地方是当你注意到
的类型时void GUIManager::handle_info( std::string )
这与指向自由函数的指针类型不同
void handle_info (std::string).
要声明指向前者的指针,您必须编写
typedef void (GUIManager::*MessageHandlerPointer)(string );
我写了一个简化的示例(使用 Foo 和 Bar :)),其中 Bar 的实例将消息转发给 Foo 的实例。这是:
#include <iostream>
#include <string>
using namespace std;
class Foo;
typedef void (Foo::*FooMessageHandlerPointer)(string ); // this is the type of a pointer to a member of Foo that gets a string and returns void.
class Bar
{
public:
Bar ( Foo* foo_, FooMessageHandlerPointer ptr )
:
foo (foo_),
p (ptr)
{}
public:
void ForwardMessage ( string s )
{
(foo->*p)(s);
}
private:
Foo* foo;
FooMessageHandlerPointer p;
};
class Foo
{
public:
void ProcessMessage (string s)
{
cout << "Foo received: " << s << "\n";
}
};
int main (void)
{
Foo foo1;
Bar bar1 ( &foo1, &Foo::ProcessMessage );
bar1.ForwardMessage( "Hello world!" );
return 0;
}
注意,在定义Bar时,它只有Foo的前向声明和成员函数指针的类型可用。 还要注意,Bar 不仅需要指向函数的指针,还需要指向实例的指针。当然,当您在 main 中创建 Bar 的实例时,您需要有权访问 headers.
希望我答对了你的问题,这对你有帮助。否则这是一个很好的练习,因为这些天我一直在玩指向成员函数的指针:)
更新: 在您发表评论之后,我认为您可能正在寻找类似委托的东西,它封装了要调用的函数,无论是自由函数还是成员函数。也许 this 话题会有所帮助