operator=() 重载的问题

最近在重构GUI 显示输出相关代码的时候,引入了一个GfxSender的类来管理。先大概说一下这个类是干什么的,以及为什么有这个需求。好吧,本质是同一件事情。就是以往gui渲染好了之后,会直接把渲染结果送给合成器,由合成器负责画面的最终输出。

现在事情变得有些复杂了,有个项目说,需要把GUI渲染好的结果share给一个别的模块,在哪里做统一的画面畸变校正,还要支持热切换。还有一个项目需要把GUI渲染好的画面通过wayland client 给weston合成。这么一来,看起来我们需要的是一个中间层GfxSender, 在这里负责把拿到的帧到底往哪里send. 我不由得脑洞打开,搞不好哪天还要支持GUI画面的编码存储等,这些都不是不可能.  以及为了应对一些没有屏幕的测试GUI框架的需求,这里是不是要搞个VirtualSender,支持将GUI存储成BMP文件.

于是我就开始了我的重构,首先是父类GfxSender,  然后是派生类CompositorClientSender,MdcClientSender, VirtualSender等。

在动手实现之前,先把测试代码写好,这样,方便我们去思考到底需要设计哪些接口,我的测试代码大致如下:

int main() {

GfxSender* base_sender = nullptr;
VirtualGfxSender * virtual_sender = new VirtualGfxSender (); 
MdcClientSender * mdc_sender = new MdcClientSender ();

base_sender = virtual_sender;
base_sender->sendFrame(fb);

base_sender = mdc_sender;
base_sender->sendFrame(fb);

delete virtual_sender;
delete mdc_sender;

return 0;
}

但是sender之间切换不是仅仅简简单单,一个赋值就能解决的事情,在从virtual_sender 切换到mdc_sender之前,需要调用一个reclaimFrame函数,该函数将会被设计成一个同步的调用,用来回收client通过这个sender 发送出去的buffer. 但是如果每次都在 = 之前干这个事情,看起来不够简洁,所以我的想法就是,重载operator=(), 在=里面做reclaim的事情,这样就好看了。

于是我的想法是这样的:

class GfxSender {
public:
  virtual void reclaimFrame(void);
virtual void sendFrame(void* fb);
virtual GfxSender* operator=(GfxSender* sender) {
     cout << "xxx" << endl;
if(typeid(*sender) != typeid(GfxSender*)) { reclaimFrame(); } return sender; } };

实时证明,我还是不太了解运算符的重载。我在测试的时候,发现base_sender在执行= 后,压根就没有变化。甚至连打印都走不进去。后来经过滕老师指点 *base_sender = mdc_sender; 才能走进重载的operator=()函数中

此时,我才恍然大悟,运算符重载只对类对象生效,对类的指针压根不会走到operator=()中去,这也是为什强行base_sender->operator=(mdc_sender)可以worker, 但是base_sender = mdc_sender不能work. 另外,即使*base_sender = mdc_sender可以执行,但是执行完后,base_sender还是原来的值,压根不会改变。因为*base_sender = mdc_sender; 被编译器翻译成:

GfxSender* operator=(this, mdc_sender);

执行完之后只是返回了mdc_sender, base_sender压根没变,所以为了base_sender能改变,就比较丑陋了,需要这么用

base_sender = *base_sender = mdc_sender;
//或者
//base_sender = base_sender->operator=(mdc_sender);

简直让人无法直视好吧,这么写代码,将会非常难以维护。我觉得这样不行,后来,我想到一个好办法,既然运算符重载是针对类的,那我干脆把GfxSender* 封装到一个wrapper类里面去,这样不就可以了吗:

class GfxSenderPtr { 
public :
  GfxSenderPtr ( GfxSenden ptr ): m ( ptr ){;} 
  GfxSenderPtr operator =( GfxSender * ptr );
  void sendFrame ( void* fb ){ m -> sendFrame ( fb );}
private :
  GfxSender *: nullptr ;

GfxSenderPtr GfxSenderPtr::operator=( GfxSender * ptr )
{
     m->reclaimFrame ();
     m =ptr;
     return m;
}

通过这种方式,我们就可以这样用了:

GfxSender * base _ sender = new GfxSender ; 、
GfxSenderPtr base _ ptr ( base _ sender );

base_ptr = mdc_sender;
 
//xxx

base_ptr = virtual_sender;

 

posted on 2021-12-25 12:12  疾速瓜牛  阅读(181)  评论(0编辑  收藏  举报

导航