繁体   English   中英

如何不为实体对象而是为指针重载箭头取消引用操作符->()

[英]How to overload the arrow dereference operator->() not for solid objects but for pointers

我知道如何为实体(堆栈)对象(如智能指针)重载operator->

#include <iostream>
struct A { void foo() {} };
struct B {
    A* pa;
    A* operator->() {
        return pa;
    }
};
int main() {
    B b;
    b->foo();  // b is SOLID object on stack: b.pa = ...
}

但是我想要这个:

B * pb = new B();
pb->foo(); // to call my overload

对于数据库管理器Singleton设计,我需要此功能:

class DatabaseManager
{
private:
    static DatabaseManager * sharedInstance_;
    sqdb::Db *db = nullptr;

public:
    static DatabaseManager * instance();
    sqdb::Db * operator->() {
        return db;
    }
}

我基本上想要这种行为

auto m = DatabaseManager::instance();
m->Query(...); // db->Query 

您不能在指针上替换->

您可以创建一个重载->的智能指针1 ,但是内置操作符可能不会重载。

auto m = DatabaseManager::instance();
m->Query(...); // db->Query 

没问题,但是m类型不是指针。 它是某些带有重载operator-> structclass

这样的类可以只是unique_ptrshared_ptr的薄包装,例如->可以返回&(ptr.get()->db)

最愚蠢的方法是

class DatabaseManager {
  struct DatabaseManagerPtr {
    DatabaseManager* ptr;
    sqdb::Db * operator->() {
      return ptr?ptr->db:nullptr;
    }
  };
  friend struct DatabaseManagerPtr;
private:
  static DatabaseManager * sharedInstance_;
  sqdb::Db *db = nullptr;

public:
  static DatabaseManagerPtr instance() {
    return {sharedInstance_};
  }
};

这会使您的“我希望它能正常工作”代码完全按原样工作,但是还有许多更聪明的方法可以做到这一点(这可能会对您的“我想让它正常工作”代码进行些微调整)


1在C ++中,智能指针是行为类似于指针的任何类型,但以合理合理的方式比原始指针“更聪明”。 也许它只是穿着一套高级西装。 C ++在称事物为“智能”指针方面不是很精英。

规则是:

如果T::operator->()存在并且如果选择运算符作为最佳匹配函数,则表达式T的类对象x的表达式x->m解释为(x.operator->())->m 。通过过载解析机制

当operator->返回时,将运算符->应用于具有原始第二个操作数的返回值。

太容易理解了:只能将.operator->()链式调用简化为单个-> ,然后也将减少“以下”对指针的取消引用。

因此,在这种情况下,只需更改instance函数以返回DatabaseManager&

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM