2015-04-16 4 views
7

При чтении предложения о добавлении в стандартную библиотеку создающей const обертки (док. N4388) я столкнулся с примером, приведенным в бумага:Как вызвать функцию класса-члена класса через элемент std :: unique_ptr

#include <memory> 
#include <iostream> 

struct A 
{ 
    void bar() const 
    { 
     std::cout << "A::bar (const)" << std::endl; 
    } 

    void bar() 
    { 
     std::cout << "A::bar (non-const)" << std::endl; 
    } 
}; 

struct B 
{ 
    B() : m_ptrA(std::make_unique<A>()) {} 

    void foo() const 
    { 
     std::cout << "B::foo (const)" << std::endl; 
     m_ptrA->bar(); // calls A::bar() (non-const) 

     // const_cast<const std::unique_ptr<A>>(m_ptrA)->bar(); // how to call the A::bar() const? 
    } 

    void foo() 
    { 
     std::cout << "B::foo (non-const)" << std::endl; 
     m_ptrA->bar(); 
    } 

    std::unique_ptr<A> m_ptrA; 
}; 

int main() 
{ 
    const B const_b; 
    const_b.foo(); 
} 

, который выводит:

B :: Foo (сопзЬ)
A :: бар (Неконстантный)

Я понимаю, почему это происходит. Даже если указатель равен const, объект, на который он указывает, не является константой, так что действительно называется функция неконстантного члена A::bar (вот в чем весь смысл предложения в документе, чтобы избежать этой кажущейся неудобной ситуации и распространять const через обертку). Кроме того, они говорят, что, чтобы избежать этой ситуации, один раз может const_cast указатель m_ptrA в B::foo() const, поэтому он называет нужный A::bar() const.

Я пробовал бесчисленные комбинации, но, честно говоря, я не знаю, как const_castunique_ptr. А именно, как я могу обеспечить в B::foo() const «правильный» звонок до A::bar() const через m_ptrA? (см. также комментарий в коде, если не совсем понятно, что я хочу).

+2

'static_cast (* PTR) .method()' –

ответ

5

Вы должны Const отливки хранимого указателя, а не unique_ptr:

const_cast<const A*>(m_ptrA.get())->bar(); 
const_cast<const A&>(*m_ptrA).bar(); 
+0

Спасибо, это действительно работает. По какой-то причине я думал, что могу использовать 'const_cast' непосредственно на интеллектуальном указателе, аналогичном' static_pointer_cast' для 'shared_ptr'. Но ваше решение, вероятно, единственный способ. – vsoftco

+0

@vsoftco 'const_cast' на интеллектуальном указателе изменяет константу интеллектуального указателя, но оператор' operator -> 'и' operator * 'умного указателя не сохраняет константу для возвращаемого объекта. Это имитирует поведение жестоких указателей. Если вам нужен константный указатель, вы можете использовать [эту реализацию] (http://stackoverflow.com/a/21065654/4538344). – StenSoft

Смежные вопросы