Ссылка указателя и оператора левого сдвига - PullRequest
2 голосов
/ 01 сентября 2011

Я переопределил оператор << и хочу получить ссылку на указатель. </p>

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

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

Где-то в коде, с экземпляром foo и службой, которая является специализацией класса BaseService, который я делаю:

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

Но я получаю эту ошибку: ошибка: нет совпадения для 'operator <<' в 'foo_instance << service_pointer' примечание: кандидаты: void foo :: operator << (BaseService * &) </p>

Ничего не изменится, если я динамически переведу свой service_pointer на BaseService

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

Есть идеи?

Ответы [ 4 ]

3 голосов
/ 01 сентября 2011

Первая версия не работает, потому что вы не можете передать ссылку на указатель на подтип, и правильно: что если реализация operator<< сделала указатель указателем на экземпляр MyService (который являетсяподкласс BaseService, но не Service)?Очевидно, что Service* было бы незаконно указывать на MyService.Поэтому передача Service* недопустима.

Вторая версия недопустима, поскольку dynamic_cast не возвращает значение l, поэтому вы не можете передать его как неконстантную ссылку.

Единственное, что вы можете сделать, это определить другую переменную типа BaseService* и передать ее в качестве аргумента <<.Если << затем переназначит указатель, это изменение будет видно только для вновь созданной переменной и не повлияет на ServicePointer.

При этом (не зная вашего варианта использования) я должен сообщить вам,operator<< принимает неконстантную ссылку на что-либо, так как его правый операнд кажется мне плохой практикой.Обычно вы не ожидаете, что << изменит свой правильный операнд.

1 голос
/ 01 сентября 2011

Тот факт, что тип Service * может быть преобразован в тип BaseService *, никоим образом не означает, что тип Service *& может быть преобразован в тип BaseService *&.Это не так.Вот почему ваш первый вызов не компилируется.

Попытка использовать dynamic_cast (или любой другой нехакерский бросок) не поможет.Результат такого броска не является lvalue.И вы не можете привязать неконстантную ссылку к чему-то, что не является lvalue.Вот почему ваш второй вызов не компилируется.

Если вы действительно хотите, чтобы ваш оператор принимал конкретно BaseService *&, тогда вы ограничены выполнением ручного предварительного преобразования Service * в lvalue. типа BaseService * (т. Е. К явному объекту-указателю), а затем вызов оператора с этим lvalue

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

Ваши вызовы оператора << будут компилироваться, если вы измените объявление, если оператордо

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

, но можете ли вы сделать это или нет, зависит от ваших намерений.Почему вы пытаетесь передать указатель по ссылке?

0 голосов
/ 01 сентября 2011

Это не может работать, потому что ссылка неконстантная, поэтому вы можете изменить значение указателя в foo :: operator <<.Рассмотрим следующий пример: </p>


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 голосов
/ 01 сентября 2011

Вы должны определить переменную BaseService.

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

Поскольку вы хотите получить ссылку на указатель, она не может быть значением.

Также обратите внимание, чтоdynamic_cast<> здесь не нужно.A static_cast<> будет в фокусе.Еще лучше использовать простое задание от service_pointer до base_service_pointer!

...