Можно ли вызывать неконстантную функцию, используя неконстантный указатель, и как будет вести себя программа, когда два unique_ptrs указывают на один и тот же объект c? - PullRequest
0 голосов
/ 11 января 2020

Первый вопрос:

Теперь у меня есть два unique_ptr s (ptrToBase и ptrToDerived), указывающие на один и тот же объект (созданный make_unique). Так что поведение программы не определено или как оно будет работать при уничтожении двух указателей?

Второй:

указатель as_const(ptrToDerived) является постоянным. как можно вызвать function2, хотя это непостоянная функция

#include <iostream>
#include<vector>

using namespace std;
class Base{

    public:
    virtual void function()const{
        cout<<"\n"<<__FUNCSIG__;
    }

    virtual~Base(){cout<<"\n"<<__FUNCSIG__;}
};




class Derived : public Base
{

    public:
    int var{9};

    virtual void function()const override{
        cout<<"\n"<<__FUNCSIG__<<"\nvar: "<<var;
    }
    void function1()const{
        cout<<"\n"<<__FUNCSIG__;
    }

    void function2(){
        cout<<"\n"<<__FUNCSIG__;
    }

    virtual~Derived(){cout<<"\n"<<__FUNCSIG__;}
};



int main()
{

    //ptr of type Base* pointing to an object of type of Derived 
    unique_ptr<Base> ptrToBase {make_unique<Derived>()};

    unique_ptr<Derived> ptrToDerived {dynamic_cast<Derived*>(ptrToBase.get())};
    if (ptrToDerived) ptrToDerived->function1();

    as_const(ptrToDerived)->function2();

    return 0;
}

Ответы [ 2 ]

2 голосов
/ 11 января 2020

Так что поведение программы не определено или как оно будет работать при уничтожении двух указателей?

Да, у него есть UB из-за двойного уничтожения. Не делайте этого.

указатель as_const (ptrToDerived) является постоянным. как функция2 может быть вызвана, хотя она является неконстантной функцией

std::as_const и сделает ее const std::unique_ptr<Derived>, а не std::unique_ptr<const Derived>, поэтому вызов function2() работает.

Это, с другой стороны, не будет работать:

unique_ptr<const Derived> ptrToDerived{dynamic_cast<Derived*>(ptrToBase.get())};

ptrToDerived->function2();

Возможные выходные данные компилятора:

source>:41:29: error: passing 'const Derived' as 'this' argument discards qualifiers [-fpermissive]

   41 |     ptrToDerived->function2();
0 голосов
/ 13 января 2020

Вы можете решить проблему двойного удаления несколькими способами.

Если вы знаете, что хотите, чтобы время жизни объекта контролировалось одним unique_ptr, вы можете создать простой наблюдатель_ptr, который будет содержать указатель, но не попытка уничтожить объект:

// a deleter that will not delete
struct no_delete
{
    template<class P> 
    void operator()(P*) const noexcept
    {
        // nothing;
    }
};

template<class T> 
using observer_ptr = std::unique_ptr<T, no_delete>;

Если вы хотите, чтобы время жизни объекта заканчивалось, когда последний из указателей выходит из области видимости, и вы не знаете, какой из них будет go сначала из области видимости, затем вы захотите std::shared_ptr

https://godbolt.org/z/vrXzFT

...