Как лучше преминить шаблон C++
От: Regard  
Дата: 27.07.07 06:45
Оценка:
Есть несколько классов с одинаковыми методами,
пожалуйста посоветуйте, как лучше применить шаблоны, чтобы
избежать повторного кода.

Пример методов классов:

// класс CDVLogin
CDVLogin & CDVLogin::operator=(const CDVLogin &r)
{
    if (this != &r)
    {
        this->CDVLogin::~CDVLogin();
        this->CDVLogin::CDVLogin(r);
    }
    return *this;
}

// класс CDVProxy
CDVProxy & CDVProxy::operator=(const CDVProxy &r)
{
    if (this != &r)
    {
        this->CDVProxy::~CDVProxy();
        this->CDVProxy::CDVProxy(r);
    }
    return *this;
}
Re: Как лучше преминить шаблон C++
От: Аноним  
Дата: 27.07.07 08:02
Оценка:
Здравствуйте, Regard, Вы писали:

R>Пример методов классов:

R>
R>// класс CDVLogin
R>CDVLogin & CDVLogin::operator=(const CDVLogin &r)
R>{
R>    if (this != &r)
R>    {
        this->>CDVLogin::~CDVLogin();
        this->>CDVLogin::CDVLogin(r);
R>    }
R>    return *this;
R>}

R>// класс CDVProxy
R>CDVProxy & CDVProxy::operator=(const CDVProxy &r)
R>{
R>    if (this != &r)
R>    {
        this->>CDVProxy::~CDVProxy();
        this->>CDVProxy::CDVProxy(r);
R>    }
R>    return *this;
R>}
R>




Обычно этот оператор через swap реализовывают
Re: Как лучше преминить шаблон C++
От: Bell Россия  
Дата: 27.07.07 08:04
Оценка:
Здравствуйте, Regard, Вы писали:

Замечание 1:
Явный вызов конструктора не разрешен стандартом языка, так что вместо явного вызова нужно использовать размещающую форму new.
С учетом этого замечания можно соорудить вот это:

template <class D>
class auto_copy
{
protected:
   void operator=(const auto_copy& rhs)
   {
      if (this != &rhs)
      {
         D* ptr = static_cast<D*>(this);
         ptr->D::~D();
         new (ptr)D(static_cast<const D&>(rhs));
      }
   }

   ~auto_copy() {}
};

class D1 : private auto_copy<D1>
{
   int n_;
public:

   D1(int n = 0) : n_(n) {}
   D1(const D1& rhs) : n_(rhs.n_) {}
};

int main()
{
   D1 d1(1), d2(2);
   d1 = d2;
   return 0;
}



В D1 operator= не определяется — все делается автоматически компилятором.

Замечание 2, более серьезное.
Саттер в "решении сложных задач" называет такой прием антиидиомой, и приводит некоторые аргументы в пользу этого высказывания.
Возможно, имеет смысл ознакомиться с этим пунктом и взвесить все "за" и "против" (это конечно если пока не читал)...
Любите книгу — источник знаний (с) М.Горький
Re[2]: Как лучше преминить шаблон C++
От: Кодт Россия  
Дата: 27.07.07 09:01
Оценка:
Здравствуйте, Bell, Вы писали:

B>Замечание 1:

B>Явный вызов конструктора не разрешен стандартом языка, так что вместо явного вызова нужно использовать размещающую форму new.
B>С учетом этого замечания можно соорудить вот это:
<>
B>В D1 operator= не определяется — все делается автоматически компилятором.

B>Замечание 2, более серьезное.

B>Саттер в "решении сложных задач" называет такой прием антиидиомой, и приводит некоторые аргументы в пользу этого высказывания.
B>Возможно, имеет смысл ознакомиться с этим пунктом и взвесить все "за" и "против" (это конечно если пока не читал)...

Действительно, антиидиома.

1) Если уж стоит задача унификации кода копирования и копирующего присваивания, то, может быть, лучше сделать наоборот:
class Foo
{
public:
    Foo(const Foo& src)
        // все члены должны быть DefaultConstructible
        // либо инициализируем их по-простому
    {
        *this = src; // а здесь выполняем присваивание
    }
    
    Foo& operator=(const Foo& rhs)
    {
        // много содержательной и нетривиальной работы
        ...
        ...
        ...
        return *this;
    }
};


2) На ровном месте получаем кучу приключений
Действительно: пусть
class Foo
{
    foo_members;
public:
    virtual ~Foo() {}
    
    Foo& operator=(const Foo& rhs)
    {
        placement_delete(this);
        placement_new(this, rhs); // (1)
        return *this;
    }
};

class Bar : public Foo
{
    bar_members;
public:
    // явно или неявно определённый оператор.
    Bar& operator=(const Bar& rhs)
    {
        (Foo&)(*this) = (const Foo&)rhs;
        bar_members = rhs.bar_members; // (2)
    }
};

Летит к чертям устойчивость к исключениям. Если в (1) будет брошено исключение, объект останется не просто в несогласованном состоянии (что, конечно, неприятно), а в разрушенном.
Невозможно наследоваться по-дефолтному. Перед (2) оказывается разрушенным весь объект Bar, а не только его база Foo.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.