免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3140 | 回复: 8
打印 上一主题 下一主题

[C++] C++网络编程高手进:基类,virtual,static,线程函数 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-07-26 18:23 |只看该作者 |倒序浏览
当然不是高手也可以进来啊^_^

是这样的,俺想写一个网络终端类,这个可以终端在不同自定义通信协议上跑。
让用户这么使用:new出一个终端,再,终端.Run();就可以了。前提是他重载了Run这个方法,就像Delphi的TThread。

思路:在基类构造函数中根据传过来的参数决定是建一个TCP还是UDP的socket,成功后创建线程,线程函数就是Run(),因为基类不知道该如何和服务器通讯,所以它是虚或纯虚的。

问题:类成员函数要求是静态或友元才能作为线程函数。静态的吧,它不能同时是虚的(virtual);如果是友员,那就是Run();而不是terminal.Run();用户可能会对到底谁在Run()有疑惑。

另外:为了保证这个终端对象的独立性(要做虚拟终端来测试),俺不想等来了一个连接再创建线程、终端对象。想让终端对象、线程、socket同生同死。

写的有点啰嗦,见谅。

谢谢!!

论坛徽章:
0
2 [报告]
发表于 2006-07-26 18:44 |只看该作者
为什么一定要run作为线程函数呢?

俺不是高手,是进来找麻烦的

[ 本帖最后由 deathbravo 于 2006-7-26 18:45 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2006-07-26 19:07 |只看该作者

  1. class Terminal
  2. {
  3. private:
  4.         staic pthread_key_t __key;
  5.         pthread_t __thid;
  6.         void* __start()(void* p){(Terminal*)p->run();}//POSIX
  7. public:
  8.         void start(){pthread_create(&__thid,NULL,__start,(void*)this);}//子类对象调用启动线程
  9. public:
  10.         virtual void run()=0;//虚函数,子类重载实现具体的功能
  11. };

  12. class TCP_Terminal:public Terminal
  13. {
  14.         void run(){}
  15. };

  16. int main()
  17. {
  18.         Terminal* terminal=new TCP_Terminal;
  19.         terminal->start();
  20. }
复制代码


无法简单地实现。
如你所说,虚函数无法作为pthread_create的参数,只能用全局函数或在基类中定义一个静态函数。
我也不是高手,代码写得比较乱,仅供参考,其中部分数据需要初始化和释放。

论坛徽章:
0
4 [报告]
发表于 2006-07-26 20:13 |只看该作者
TO:deathbravo
为什么一定要run作为线程函数呢?


.
为了用户,呵呵,目前就是俺了,使用方便。把一个终端当作一个线程来用,或者反过来,把线程当终端。但是线程、socket的建立在我new出一个终端对象的时候就已经由基类给做好了。比如我只要重载一下基类的run()这个函数,再new MyTerminal(127.0.0.1,8060,"TCP");就成了,岂不简单?

[ 本帖最后由 csoapy 于 2006-7-26 20:18 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2006-07-26 20:47 |只看该作者
谢谢hezhiroy (忍着)!
俺就觉的会有办法嘛!其实_beginthread()对其参数:函数地址的要求也就是想要一个“确定的地址”罢了,而我们可以在利用语言规则做一点“手脚”来达到目的--编译器是死的,人是活的。我是这么理解的。
小弟C++新手,以后还会有更多问题请教!来CU四年光潜水去了!

论坛徽章:
0
6 [报告]
发表于 2006-07-27 09:24 |只看该作者
to:hezhiroy
void * __start()(void* p){(Terminal*)p->run();}//POSIX

你的意思是定义一个__start的函数指针?,它指向这样一个函数 void func(void *p){(Terminal*)p->run();}?

论坛徽章:
0
7 [报告]
发表于 2006-07-27 09:44 |只看该作者
原帖由 csoapy 于 2006-7-26 18:23 发表
当然不是高手也可以进来啊^_^

是这样的,俺想写一个网络终端类,这个可以终端在不同自定义通信协议上跑。
让用户这么使用:new出一个终端,再,终端.Run();就可以了。前提是他重载了Run这个方法,就像Delphi的 ...


不知道该怎么作,不过感觉好像和我前一阵子看的libjingle里的TCP或者UDP的socket建立和线程的运行
有些相似
可以参考一下,但不能和lz的需求不会完全相同。

论坛徽章:
0
8 [报告]
发表于 2006-07-27 12:42 |只看该作者
TO:hezhiroy (忍着)
我在VC6上把你的代码改了一下,用了static,这个样子:
class Terminal
{
private:       
        static void __start( void *p){ ((Terminal*)p)->run(); }
public:
        void start() { _beginthread(__start, 0, (void*)this);}
public:
        virtual void run()=0;//虚函数,子类重载实现具体的功能
};

class TCP_Terminal:public Terminal
{
        void run() { cout << "TCP_Terminal's run!" << endl; }
};

int main()
{
        TCP_Terminal* terminal=new TCP_Terminal;
        cout << "before\n";
        terminal->start();
        Sleep(3000);
        cout << "after\n";
        return 0;
}

现在的问题是,类的使用都可能觉得与其->start()还不如直接用自己刚刚重载的->run();于是他就直接run()了,这样也就没法启动线程了,能否阻止他这么做,同时又让他必须重载run()呢?

论坛徽章:
0
9 [报告]
发表于 2006-07-27 13:06 |只看该作者
呵呵,可以了,如果调用了->run();编译就通不过,说是不能访问私有成员。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP