static_cast и временное создание (окончательная редакция) - PullRequest
4 голосов
/ 21 декабря 2011

Prerequisities: Чтобы понять этот вопрос, сначала прочтите следующий вопрос и ответ на него: Приведение auto_ptr к auto_ptr

В Приведите auto_ptr к auto_ptr Стив ответил, что "Ваш static_cast скопирует auto_ptr во временное состояние, и поэтому sS будет сброшен, а ресурс будет уничтожен, когда временное состояние (( в конце выписки). "

Меня интересует процесс временного создания, пока вызывается static_cast. Я хотел бы иметь код, который я могу проследить, чтобы увидеть этот эффект. Я не могу использовать static_cast<auto_ptr<Circle>> ..., потому что он не может быть скомпилирован, поэтому мне нужно написать некоторый класс моделирования вместо auto_ptr и наблюдать за процессом временного создания.

Я также понимаю, что временное создание тесно связано с вызовом конструктора копирования. Потеря владения auto_ptr моделируется с присвоением копии, которое устанавливает поле источника _radius в отрицательное значение (мне нужна простая логическая модель auto_ptr).

Итак, я предлагаю следующий Circle класс:

#include <iostream>

class Shape {};

class Circle: public Shape {
  double _radius;
public:
  explicit Circle(double radius = .5): _radius(radius) {}
  Circle &operator =(Circle &circle) {
    _radius = circle._radius;
    circle._radius = -1.;
    return *this;
  }
  Circle(Circle &circle) { *this = circle; }
  double GetRadius() { return _radius; }
};

int wmain() {
  using namespace std;

  Circle c1(100), c2(200), c3(300);
  c2 = c3;

  Shape *s1, s2;
  s1 = &c1;
  wcout << static_cast<Circle *>(s1)->GetRadius() << endl;

  return 0;
}

Ok. Здесь мы видим, что «передача права собственности» происходит в c2 = c3. НО я не могу добиться временного создания в static_cast.

Вопрос: как сделать небольшую симуляцию создания временного объекта при static_cast?

Мне кажется, Стив, что временный объект создается во время каста. Единственное, что я хочу, это написать пример, показывающий временное создание . Эта цель имеет академические причины.

Может кто-нибудь уточнить, как добиться эффекта, описанного в ответе Стива, который он разместил в указанной теме?

Ответы [ 4 ]

3 голосов
/ 21 декабря 2011

В вашем предыдущем вопросе auto_ptr - это класс, который владеет, и при копировании сбрасывает указатель источника на null.

Теперь Circle - это класс, имитирующий владение, путем сброса его радиуса на -1 при копировании. Таким образом, это похоже на auto_ptr таким образом, но никак иначе.

Итак, чтобы наблюдать потерю смоделированного владения, вам нужно скопировать Circle, что вы и делаете с присвоением копии в строке c2 = c3. Приведение Circle* не копирует объект, только указатель, но приведение Circle копирует объект:

int main() {
    Circle c1(100);
    static_cast<Circle>(c1);
    std::cout << c1.GetRadius() << '\n';
}

Выход -1.

Или, если вы специально хотите увидеть его с приведением к производному классу:

struct SpecialCircle: Circle {
    SpecialCircle(Circle &circle) : Circle(circle) {}
    explicit SpecialCircle(double radius = .5): Circle(radius) {}
};

int main() {
    SpecialCircle s1(100);
    Circle &c1 = s1;
    static_cast<SpecialCircle>(c1);
    std::cout << c1.GetRadius() << '\n';
}
1 голос
/ 21 декабря 2011

Ок.Здесь мы можем видеть, что «передача права собственности» происходит в c2 = c3.НО я не могу добиться временного создания в static_cast.

static_cast<Circle> (c2); 

"украдет" у c2.

0 голосов
/ 21 декабря 2011

Самое простое, о чем я мог подумать, это (если вы измените пример в ваш первоначальный вопрос ):

wcout << aS->GetName() << L'\t' << static_cast<auto_ptr<Circle>>(aS.get())->GetRadius() << endl;

Это:

static_cast<auto_ptr<Circle>>(aS.get())

создаетвременный тип auto_ptr< Circle >, который уничтожает объект типа auto_ptr< Shape > в конце области.

Вот пример (надеюсь, он достаточно понятен):

#include <iostream>
#include <memory>

struct B
{
    ~B()
    {
        std::cout<<"~B"<<std::endl;
    }
    void foo()
    {
        std::cout<<"foo"<<std::endl;
    }
};
struct A : B
{
    ~A()
    {
        std::cout<<"~A"<<std::endl;
    }
    void bar()
    {
        std::cout<<"boom"<<std::endl;
    }
};

int main() {
    std::auto_ptr< A > a( new A );
    {
        std::auto_ptr< B > b( a.get() );
        b->foo();
    }

    std::cout<<"prepare for the crash"<<std::endl;
}
0 голосов
/ 21 декабря 2011

Вы в порядке с auto_ptr. Как объясняет ответ Стива , язык достаточно умен, чтобы делать это с обычными указателями. Приведение указателя между базовым и производным классами может потребовать изменения значения указателя, и static_cast сделает это при необходимости.

...