如何重载箭头取消引用 operator->() 不是针对实体对象而是针对指针
How to overload the arrow dereference operator->() not for solid objects but for pointers
我知道如何为实体(堆栈)对象(如智能指针)重载运算符->
#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
的类型不是指针。这将是一些 struct
或 class
与超载 operator->
.
这样的 class 可以只是 unique_ptr
或 shared_ptr
的薄包装,而 ->
可以 return &(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_};
}
};
这使您的 "I want this to work" 代码完全按原样工作,但还有许多更聪明的方法可以做到这一点(可能涉及对您的 "I want this to work" 代码进行轻微调整)
1 在 C++ 中,智能指针是任何类似于指针的类型,但在某种程度上 "smarter" 比原始指针合理.也许只是穿了一套比较花哨的西装; C++ 在调用事物 "smart" 指针方面不是很精英。
规则是:
An expression x->m
is interpreted as (x.operator->())->m
for a class object x
of type T
if T::operator->()
exists and if the operator is selected as the best match function by the overload resolution mechanism
和
When operator-> returns, the operator -> is applied to the value
returned, with the original second operand.
太容易理解了:只有 .operator->()
的链式调用可以减少为单个 ->
然后下面的指针解引用也将是 "reduced".
所以在这种情况下只需将instance
函数更改为returnDatabaseManager&
我知道如何为实体(堆栈)对象(如智能指针)重载运算符->
#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
的类型不是指针。这将是一些 struct
或 class
与超载 operator->
.
这样的 class 可以只是 unique_ptr
或 shared_ptr
的薄包装,而 ->
可以 return &(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_};
}
};
这使您的 "I want this to work" 代码完全按原样工作,但还有许多更聪明的方法可以做到这一点(可能涉及对您的 "I want this to work" 代码进行轻微调整)
1 在 C++ 中,智能指针是任何类似于指针的类型,但在某种程度上 "smarter" 比原始指针合理.也许只是穿了一套比较花哨的西装; C++ 在调用事物 "smart" 指针方面不是很精英。
规则是:
An expression
x->m
is interpreted as(x.operator->())->m
for a class objectx
of typeT
ifT::operator->()
exists and if the operator is selected as the best match function by the overload resolution mechanism
和
When operator-> returns, the operator -> is applied to the value returned, with the original second operand.
太容易理解了:只有 .operator->()
的链式调用可以减少为单个 ->
然后下面的指针解引用也将是 "reduced".
所以在这种情况下只需将instance
函数更改为returnDatabaseManager&