开发者

Reference of pointer and left shift operator

开发者 https://www.devze.com 2023-04-01 00:20 出处:网络
I have redefined the << operator and I want it to take a reference of pointer. class foo { foo(); virtual ~foo();

I have redefined the << operator and I want it to take a reference of pointer.

class foo
{
    foo();
    virtual ~foo();

    void operator << (BaseService*& iRight);
}

Somewhere in the code, having a foo instance, a开发者_C百科nd a service which is a specialization of the BaseService class I do :

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

But I get this error : error: no match for 'operator<<'in 'foo_instance << service_pointer' note: candidates are: void foo::operator<<(BaseService*&)

Nothing changes if I dynamic_cast my service_pointer to BaseService

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

Any idea ?


The first version does not work because you can't pass in a reference to a pointer to a subtype and rightly so: What if the implementation of operator<< made the pointer point to an instance MyService (which is a subclass of BaseService, but not of Service)? Clearly it would be illegal for a Service* to point to a MyService. So passing in a Service* is not allowed.

The second version is not allowed because dynamic_cast does not return an l-value, so you can't pass it as a non-const reference.

The only thing you can do is define another variable of type BaseService* and pass that as an argument to <<. If << then reassigns the pointer, that change will be visible for the newly created variable only and not affect ServicePointer.

That being said (and not knowing your use case) I have to advice you that having operator<< take a non-const reference to anything as its right operand strikes me as bad practice. You wouldn't usually expect << to modify it's right operand.


Just because Service * type is convertible to BaseService * type does not in any way mean that Service *& type is convertible to BaseService *& type. It isn't. This is why your first call does not compile.

Trying to use dynamic_cast (or any other non-hacking cast) will not help. The result of such cast is not an lvalue. And you cannot bind a non-const reference to something that is not an lvalue. This is why your second call does not compile.

If you really want your operator to accept specifically BaseService *&, then you are limited to performing a manual pre-conversion of Service * to an lvalue of type BaseService * (i.e. to an explicit pointer object) and then calling the operator with that lvalue

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

Your calls to operator << will compile if you change the declaration if the operator to

void operator <<(BaseService* const& iRight);

but whether you can do it or not depends on your intent. Why are you trying to pass a pointer by reference?


You have to actually define a BaseService pointer variable.

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

As you want to take a reference to the pointer, it cannot be an rvalue.

Also note that the dynamic_cast<> it not necessary here. A static_cast<> would to the trick. Even better, use a simple assignment from service_pointer to base_service_pointer!


This can't possibly work because reference is non-const, so you can change the pointer value in foo::operator<<. Consider the following example:


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...

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号