Там кто-либо - автоматизированный способ реализовать постконструктора и предварительный деструктор виртуальные вызовы метода?

Если подытожить, что люди здесь говорят, json_decode / encode кажется быстрее, чем сериализация / десериализация, НО Если вы сделаете var_dump, тип сериализованного объекта будет изменен. Если по какой-то причине вы хотите сохранить тип, переходите к serialize!

(попробуйте, например, stdClass vs array)

serialize / unserialize:

Array cache:
array (size=2)
  'a' => string '1' (length=1)
  'b' => int 2
Object cache:
object(stdClass)[8]
  public 'field1' => int 123
This cache:
object(Controller\Test)[8]
  protected 'view' => 

json encode / decode

Array cache:
object(stdClass)[7]
  public 'a' => string '1' (length=1)
  public 'b' => int 2
Object cache:
object(stdClass)[8]
  public 'field1' => int 123
This cache:
object(stdClass)[8]

Как вы можете видеть, json_encode / decode преобразует все в stdClass, что не очень хорошо, информация об объекте теряется ... Так что решайте исходя из потребностей, особенно если это не только массивы. ..

13
задан j0k 1 July 2013 в 14:09
поделиться

7 ответов

Основная проблема с добавлением пост-конструкторов в C ++ заключается в том, что еще никто не установил, как обращаться с конструкторами пост-пост, пост-пост-постконструкторами и т. Д.

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

Как показывает ваш пример (возможно, вы не понимаете), они не нужны :

MyObject * obj = new MyObject;
obj->Initialize();   // virtual method call, required after ctor for (obj) to run properly

obj->AboutToDelete();  // virtual method call, required before dtor for (obj) to clean up properly
delete obj;

Пусть ' s показывают , почему эти методы не нужны. Эти два вызова могут вызывать виртуальные функции из MyObject или одной из его баз. Однако MyObject :: MyObject () также может безопасно вызывать эти функции. После возврата MyObject :: MyObject () ничего не происходит, что сделало бы obj-> Initialize () безопасным. Таким образом, либо obj-> Initialize () неверен, либо его вызов может быть перемещен в MyObject :: MyObject () . Та же самая логика применяется в обратном порядке к obj-> AboutToDelete () . Самый производный деструктор будет запущен первым, и он по-прежнему может вызывать все виртуальные функции, включая AboutToDelete () .

MyObject :: MyObject () также может безопасно вызывать эти функции. После возврата MyObject :: MyObject () ничего не произойдет, что сделало бы obj-> Initialize () безопасным. Таким образом, либо obj-> Initialize () неверен, либо его вызов может быть перемещен в MyObject :: MyObject () . Та же самая логика применяется в обратном порядке к obj-> AboutToDelete () . Самый производный деструктор будет запущен первым, и он по-прежнему может вызывать все виртуальные функции, включая AboutToDelete () .

MyObject :: MyObject () также может безопасно вызывать эти функции. После возврата MyObject :: MyObject () ничего не произойдет, что сделало бы obj-> Initialize () безопасным. Таким образом, либо obj-> Initialize () неверен, либо его вызов может быть перемещен в MyObject :: MyObject () . Та же самая логика применяется в обратном порядке к obj-> AboutToDelete () . Самый производный деструктор будет запущен первым, и он все еще может вызывать все виртуальные функции, включая AboutToDelete () .

Initialize () неверна или ее вызов может быть перемещен в MyObject :: MyObject () . Та же самая логика применяется в обратном порядке к obj-> AboutToDelete () . Самый производный деструктор будет запущен первым, и он все еще может вызывать все виртуальные функции, включая AboutToDelete () .

Initialize () неверна, или ее вызов может быть перемещен в MyObject :: MyObject () . Та же самая логика применяется в обратном порядке к obj-> AboutToDelete () . Самый производный деструктор будет запущен первым, и он по-прежнему может вызывать все виртуальные функции, включая AboutToDelete () .

-1
ответ дан 1 December 2019 в 23:15
поделиться

Хотя автоматизированного способа не существует, вы можете заставить пользователей передать данные, запретив им доступ к деструктору этого типа и объявив специальный метод удаления. В этом методе вы можете делать виртуальные вызовы, которые хотите. Создание может использовать тот же подход, что и статический фабричный метод.

class MyObject {
  ...
public:
  static MyObject* Create() { 
    MyObject* pObject = new MyObject();
    pObject->Initialize();
    return pObject;
  }
  Delete() {
    this->AboutToDelete();
    delete this;
  }
private:
  MyObject() { ... }
  virtual ~MyObject() { ... }
};

Теперь невозможно вызвать "удалить объект;" если сайт вызова не имеет доступа к закрытым членам MyObject.

10
ответ дан 1 December 2019 в 23:15
поделиться

Лучшее, что я могу придумать, - это реализовать ваш собственный интеллектуальный указатель с помощью статического метода Create, который обновляет экземпляр и вызывает Initialize, а в его деструкторе вызывает AboutToDelete и затем delete.

3
ответ дан 1 December 2019 в 23:15
поделиться

Я использовал очень тщательно разработанный фабричный метод Create () (статический член каждого класса) для вызова пары конструктор и инициализатор в том же порядке, в котором C # инициализирует типы. Он вернул shared_ptr экземпляру типа, гарантируя выделение кучи. Со временем он оказался надежным и непротиворечивым.

Уловка: я сгенерировал свои объявления классов C ++ из XML ...

2
ответ дан 1 December 2019 в 23:15
поделиться

За исключением JavedPar's Идея метода предварительного разрушения, не существует готового решения, позволяющего легко выполнить двухэтапное построение / разрушение в C ++. Самый очевидный способ сделать это - следовать наиболее распространенному ответу на проблемы в C ++: «Добавьте еще один уровень косвенности». Вы можете заключить объекты этой иерархии классов в другой объект. Затем конструкторы / деструкторы этого объекта могут вызывать эти методы. Посмотрите, например, на идиому Couplien с конвертами букв или воспользуйтесь уже предложенным подходом с умным указателем.

2
ответ дан 1 December 2019 в 23:15
поделиться

http://www.research.att.com/~bs/wrapper.pdf Эта статья от Страуструпа решит вашу проблему.

Я тестировал это в VS 2008 и на UBUNTU против компилятора g ++. Он работал нормально.

#include <iostream>

using namespace std;

template<class T>

class Wrap
{
    typedef int (T::*Method)();
    T* p;
    Method _m;
public:
    Wrap(T*pp, Method m): p(pp), _m(m)  { (p->*_m)(); }
    ~Wrap() { delete p; }
};

class X
{
public:
    typedef int (*Method)();
    virtual int suffix()
    {
        cout << "X::suffix\n";
        return 1;
    }

    virtual void prefix()
    {
        cout << "X::prefix\n"; 
    }

    X() {  cout << "X created\n"; }

    virtual ~X() { prefix(); cout << "X destroyed\n"; }

};

class Y : public X
{
public:
    Y() : X() { cout << "Y created\n"; }
    ~Y() { prefix(); cout << "Y destroyed\n"; }
    void prefix()
    {
        cout << "Y::prefix\n"; 
    }

    int suffix()
    {
        cout << "Y::suffix\n";
        return  1;
    }
};

int main()
{
    Wrap<X> xx(new X, &X::suffix);
    Wrap<X>yy(new Y, &X::suffix);
}
2
ответ дан 1 December 2019 в 23:15
поделиться

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

template<typename Base> 
class Derived : public Base {
    // You'd need C++0x to solve the forwarding problem correctly.
    Derived() : Base() {
        Initialize();
    }
    template<typename T>
    Derived(T const& t): Base(t) {
        Initialize();
    }
    //etc
private:
    Initialize();
};
-1
ответ дан 1 December 2019 в 23:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: