如何用 RHS 上的引用指针重载 operator<<?

How to overload operator<< with a reference pointer on the RHS?

我试图了解如何使用 RHS 上的指针变量正确重载运算符 <<,使用参考参数。这是一个示例代码:

#include <iostream>
using namespace std;

class A
{
 public:
   void print(ostream& out) const { out << "Hello World!"; }
};

ostream& operator<<(ostream& out, const A*& handle)
{
   handle->print(out);
   return out;
}

int main() {
   A *a = new A();
   cout << a << endl;
   delete a;
}

我假设结果应该是 Hello World!。相反,该程序打印对象 a 0x7f9bc6405be0 的地址,因此显然 cout << a 没有调用我的重载函数。

谁能解释一下为什么我对重载 << 的定义没有像我预期的那样工作?

#include <iostream>
using namespace std;

class A
{
 public:
   void print(ostream& out) const { out << "Hello World!"; }
};

ostream& operator<<(ostream& out, const A*& handle)
{
   handle->print(out);
   return out;
}

int main() {
   A *a = new A();
   cout << a << endl;
   delete a;
}

operator<< 函数需要引用代码中的 A 对象指针。例如,您可以使用 ref to pointer 函数来更改参数的地址,因为如果您通过发送指针和期望指针来调用该函数,如下所示,那么该函数会将对象的地址复制到该指针指向以在它的堆栈并丢失了指针的地址,因此该函数无法更改参数的地址。

您可以通过两种方式更改签名,然后就可以了:

ostream& operator<<(ostream& out, const A* handle)

在这里,调用者调用传递值为 A* 的函数,然后在函数内部访问打印函数。

关于您的另一个问题的第二种方法,通过向 main 函数中的变量添加 const 关键字或删除函数签名中的 const 关键字来纠正不匹配。将非常量指针隐式转换为对指针的常量引用可能会产生无效状态:

int* p;
const int x;
// a now reference to pointer p; it is not valid operation sure
const int*& a = p;  
// if this operation was allowed and if we also changed the address
// to that p points 
*a = &x;
// then it would allow p to access and change const so we would change const data through non-cont pointer. 

 

鉴于目前的评论,我做了更多的实验。这一切都归结为调用和函数签名之间的匹配。以下代码对此进行了演示:

#include <iostream>
using namespace std;

void test(int& a) { // I can remove this function.
   cout << "void test(int& a): a = "
        << a << endl;
}

void test(const int& a) {
   cout << "void test(const int& a): a = "
        << a << endl;
}

void test(int*& a) { // I cannot remove this function.
   cout << "void test(int*& a): a = "
        << *a << endl;
}

void test(const int*& a) {
   cout << "void test(const int*& a): a = "
        << *a << endl;
   a = a + 3;
}

int main() {
   int a = 2, c = 5;
   const int b = 3, d = 7;
   int* pc = &c;
   const int* pd = &d;
   test(a);
   test(b);
   test(pc);
   test(pd);
}  

代码打印

void test(int& a): a = 2
void test(const int& a): a = 3
void test(int*& a): a = 5
void test(const int*& a): a = 7

奇怪的是,我可以删除函数 void test(int& a) 并且调用 test(a) 将使用函数 void test(const int& a)。相比之下,我无法删除函数 void test(int*& a) 并且调用 test(pc) 仍然不匹配函数 void test(const int*& a).

如果有人能在评论中解释这种差异,我可以将此问题标记为已回答。

我猜测——本着类似重载函数的精神——你试图让你的参数成为一个常量引用。即,对 const 对象的引用。

您的参数:

 const A*& handle

不是常量引用。它是 (reference &) 到 (mutable pointer *) 到 (const A).

将您的参数更改为此,它将起作用:

 A *const & handle

这是一个 (reference &) 到一个 (const pointer *const) 到一个 (A).

A 是否为 const 取决于您和您的代码的意图。

查看它在 Compiler Explorer 中的工作情况。