指针和左移操作符的引用

Reference of pointer and left shift operator

本文关键字:引用 操作符 左移 指针      更新时间:2023-10-16

我已经重新定义了<操作符,我想让它接受指针的引用。>

class foo
{
    foo();
    virtual ~foo();
    void operator << (BaseService*& iRight);
}

在代码的某个地方,有一个foo实例,和一个服务,它是BaseService类的专门化我做:

Service* service_pointer = new Service();
foo_instance << service_pointer;

但是我得到这个错误:错误:在foo_instance <<中没有匹配'operator<<'service_pointer"注:候选对象为:void foo::operator<<(BaseService*&)

如果我将service_pointer动态强制转换为BaseService,没有任何变化

Service* service_pointer = new Service();
foo_instance << dynamic_cast<BaseService*>(service_pointer);

第一个版本不工作,因为你不能传递一个指向子类型的指针的引用,正确的是:如果operator<<的实现使指针指向实例MyService(这是BaseService的子类,但不是Service)怎么办?显然,Service*指向MyService是非法的。因此不允许传入Service*

第二个版本是不允许的,因为dynamic_cast不返回l值,所以你不能将它作为非const引用传递。

您唯一能做的就是定义另一个类型为BaseService*的变量,并将其作为参数传递给<<。如果<<然后重新分配指针,这个变化将只对新创建的变量可见,而不影响ServicePointer

话虽这么说(不知道你的用例),我不得不建议你,让operator<<把对任何东西的非const引用作为它的右操作数,这对我来说是不好的做法。你通常不会期望<<修改它的右操作数

仅仅因为Service *类型可以转换为BaseService *类型并不意味着Service *&类型可以转换为BaseService *&类型。它不是。这就是为什么你的第一个调用没有编译。

尝试使用dynamic_cast(或任何其他非黑客强制转换)将无济于事。这种强制转换的结果不是左值。你不能将非const引用绑定到非左值。这就是为什么你的第二个调用不能编译。

如果你真的想让你的运算符接受BaseService *&,那么你只能手动将Service *预转换为BaseService *类型的左值(即显式指针对象),然后用该左值

调用运算符。
Service* service_pointer = new Service();
BaseService* base_service_pointer = service_pointer;
foo_instance << base_service_pointer;

如果将操作符更改为

,则对操作符<<的调用将编译。
void operator <<(BaseService* const& iRight);

但是你是否能做到这一点取决于你的意图。为什么你试图通过引用传递一个指针?

您必须实际定义一个BaseService指针变量。

Service* service_pointer = new Service();
BaseService* base_service_pointer = dynamic_cast<BaseService*>(service_pointer);
foo_instance << base_service_pointer;

当你想引用指针时,它不能是右值。

还要注意,dynamic_cast<>在这里不是必需的。static_cast<>就可以了。甚至更好,使用一个简单的从service_pointerbase_service_pointer的赋值!

这可能不起作用,因为引用是非const的,所以您可以在foo::operator<<中更改指针值。考虑下面的例子:

<>之前 class Service1 : BaseService { }; class Service2 : BaseService { }; void foo::operator << (BaseService*& iRight) { // ok, iRight is a reference to BaseService* // so we can assign Service2* to it, can't we? iRight = new Service2(); } Service1* service_pointer = new Service1(); foo_instance << service_pointer; // oops...