c++ - 如何重载箭头取消引用运算符->() 不是针对实体对象而是针对指针

标签 c++ operator-overloading operators

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

#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

我需要这个来进行数据库管理器单例设计:

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++ 在将事物称为“智能”指针方面并不是非常精英主义。

关于c++ - 如何重载箭头取消引用运算符->() 不是针对实体对象而是针对指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46097535/

相关文章:

c++ - std::ios_base::ios_base(const std::ios_base) 是私有(private)的

c++ - 为命名空间中的类模板重载输出运算符

javascript - Javascript 中数组的重载 [] 运算符

c++ - 如何为聚合结构实现 C++ (in)equality operators?

c++ - 使用 C++20 fmt 限制结果的总大小

c++ - 如何在 ADL 期间使功能模板成为最低优先级?

f# - 这个管道元组运算符是否已经存在*某处?

c++ - boost::operators 混合算术

c++ - 如何在c++多线程环境下实现定时器

android - gradle experimental 通过 srcDir srcFile 指令包含文件目录