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...
精彩评论