Вопрос про присваивание объектов
От: Максим Рогожин Россия  
Дата: 24.04.11 11:31
Оценка:
Добрый день!

Допустим, есть некий класс X, в общем случае производный от каких-то еще классов. Как определить можно ли объекты класса X присваивать друг другу:

X f();
X x;
x = f();


Правильно ли я понимаю, что для этого нужно просмотреть определение класса X и всех его базовых классов и убедиться, что в каждом из них имеется либо реализованный operator= либо корректно работающий дефолтный operator= ?

+ Аналогичный вопрос про конструирование копированием:

void g(X);
X x;
g(x);


Объясните, пожалуйста.
Re: Вопрос про присваивание объектов
От: Abyx Россия  
Дата: 24.04.11 11:34
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

[...]

что значит "определить" — скомпилировать и посмотреть будет ошибка компиляции или нет?
In Zen We Trust
Re: Вопрос про присваивание объектов
От: MasterZiv СССР  
Дата: 24.04.11 11:39
Оценка:
On 24.04.2011 15:31, Максим Рогожин wrote:

> Допустим, есть некий класс X, в общем случае производный от каких-то еще

> классов.

Для начала нужно сказать, что для operator = не может быть динамического
полиморфизма в рантайме. Т.е. как бы operator = никогда не "виртуальный".
Ну т.е. динамический полиморфизм работать не будет.


Как определить можно ли объекты класса X присваивать друг другу:
>
> X f();
> X x;
> x = f();

Если есть публичный X::operator = — можно будет присваивать


> Правильно ли я понимаю, что для этого нужно просмотреть определение класса X и

> всех его базовых классов

Без базовых. В этом классе только. Хотя как написать код ... да, может и базовые
надо глядеть.

и убедиться, что в каждом из них имеется либо
> реализованный operator= либо корректно работающий дефолтный operator= ?

Да.

>

> + Аналогичный вопрос про конструирование копированием:
>
> void g(X);
> X x;
> g(x);

То же самое, только если есть публичный X::X( const X& )

Ну или если есть дефолтные предоставляемые компилятором.
Posted via RSDN NNTP Server 2.1 beta
Re: Вопрос про присваивание объектов
От: rg45 СССР  
Дата: 24.04.11 13:13
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Допустим, есть некий класс X, в общем случае производный от каких-то еще классов. Как определить можно ли объекты класса X присваивать друг другу:


Думаю, формализовать можно примерно так:

  1. Если в классе определен открытый оператор копирующего присваивания, то копирующее присваивание разрешено;
  2. Если в классе оператор копирующего присваивания объявлен закрытым, то копирующее присваивание запрещено;
  3. Если в классе оператор копирующего присваивания не объявлен, то копирующее присваивание разрешено во всех случаях, кроме следующих:
    • В классе содержатся нестатические члены-ссылки;
    • В классе содержатся нестатические члены, для которых запрещено копирующее присваивание;
    • Для какого-либо из непосредственных базовых классов запрещено копирующее присваивание.

Разрешено ли копирующее присваивание для каждого базового класса определяем, разумеется, по этим же правилам.

Правила для копирующих конструкторов будут выглядеть аналогично.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Вопрос про присваивание объектов
От: Lorenzo_LAMAS  
Дата: 24.04.11 13:26
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>On 24.04.2011 15:31, Максим Рогожин wrote:


>> Допустим, есть некий класс X, в общем случае производный от каких-то еще

>> классов.

MZ>Для начала нужно сказать, что для operator = не может быть динамического

MZ>полиморфизма в рантайме. Т.е. как бы operator = никогда не "виртуальный".
MZ>Ну т.е. динамический полиморфизм работать не будет.

class A
{
public:
   virtual A & operator = (const A &);
};

class B : public A
{
public:
   virtual A & operator = (const A &);
};

int main()
{
   B b;
   A & ra = b;
   B c;
   ra = c; 
}
Of course, the code must be complete enough to compile and link.
Re: Вопрос про присваивание объектов
От: Максим Рогожин Россия  
Дата: 24.04.11 14:39
Оценка:
Спасибо всем за ответы! Но, я немного другое хотел спросить, я хотел спросить как определить что присваивание будет корректно. Например:

class A {
// только дефолтный operator=
A() {_buff = new int[1024];}
~A(){ delete _buff;}
private:
   int* _buff;
};

class B : public A {
// только дефолтный operator=
private:
   std::string _name;
};


Глядя только на класс B можно подумать, что объекты B можно присваивать друг другу. Но в базовом классе operator= будет некорректно работать с _buff; (просто указатель скопирует).
Re[2]: Вопрос про присваивание объектов
От: rg45 СССР  
Дата: 24.04.11 14:45
Оценка: 2 (1) +1
Здравствуйте, Максим Рогожин, Вы писали:

МР>Спасибо всем за ответы! Но, я немного другое хотел спросить, я хотел спросить как определить что присваивание будет корректно. Например:


МР>
МР>class A {
МР>// только дефолтный operator=
МР>A() {_buff = new int[1024];}
МР>~A(){ delete _buff;}
МР>private:
МР>   int* _buff;
МР>};

МР>class B : public A {
МР>// только дефолтный operator=
МР>private:
МР>   std::string _name;
МР>};
МР>


МР>Глядя только на класс B можно подумать, что объекты B можно присваивать друг другу. Но в базовом классе operator= будет некорректно работать с _buff; (просто указатель скопирует).


Эту проблему должен решать разработчик класса A, а не пользователь. Разработчик должен либо реализовать копирование корректно (у него просто уйма вариантов сделать это), либо запретить копирование вовсе.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Вопрос про присваивание объектов
От: MasterZiv СССР  
Дата: 24.04.11 15:25
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, MasterZiv, Вы писали:


MZ>>On 24.04.2011 15:31, Максим Рогожин wrote:


>>> Допустим, есть некий класс X, в общем случае производный от каких-то еще

>>> классов.

MZ>>Для начала нужно сказать, что для operator = не может быть динамического

MZ>>полиморфизма в рантайме. Т.е. как бы operator = никогда не "виртуальный".
MZ>>Ну т.е. динамический полиморфизм работать не будет.

L_L>[ccode]

L_L>class A
L_L>{
L_L>public:
L_L> virtual A & operator = (const A &);
L_L>};

L_L>class B : public A

L_L>{
L_L>public:
L_L> virtual A & operator = (const A &);
L_L>};


А толку-то ? Справа-то const A& ...
Re[2]: Вопрос про присваивание объектов
От: MasterZiv СССР  
Дата: 24.04.11 15:26
Оценка: 2 (1)
Здравствуйте, Максим Рогожин, Вы писали:

МР>Спасибо всем за ответы! Но, я немного другое хотел спросить, я хотел спросить как определить что присваивание будет корректно. Например:

МР>Глядя только на класс B можно подумать, что объекты B можно присваивать друг другу. Но в базовом классе operator= будет некорректно работать с _buff; (просто указатель скопирует).

Никак, только код читать.
Re[4]: Вопрос про присваивание объектов
От: Lorenzo_LAMAS  
Дата: 24.04.11 16:14
Оценка:
MZ>А толку-то ? Справа-то const A& ...

Это демонстрация того, что твое утверждение про невозможность динамического полиморфизма для оператора присваивания — не всегда верно. Полиморфизм есть. Динамический.
Of course, the code must be complete enough to compile and link.
Re[5]: Вопрос про присваивание объектов
От: MasterZiv СССР  
Дата: 24.04.11 20:35
Оценка:
On 24.04.2011 20:14, Lorenzo_LAMAS wrote:

> Это демонстрация того, что твое утверждение про невозможность динамического

> полиморфизма для оператора присваивания — не всегда верно. Полиморфизм есть.
> Динамический.

Да, есть. На одну половину стороны присваивания

Да не, можно и в базовом классе объявить все возможные варианты
присваивания справа от = в виде виртуальных методов,
да толку-то... мало того, что ВСЕ классы в иерархии должны быть
заранее известны и перечислены в базовом классе, так ещё если
что добавится -- нужно ВО ВСЕХ классах переопределять метод.

А так -- нормально, полный динамический полиморфизм.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: Вопрос про присваивание объектов
От: Erop Россия  
Дата: 25.04.11 21:28
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>А так -- нормально, полный динамический полиморфизм.


Можно NVI заюзать, если так уж приспичило. Но главная проблема тут в другом. Не понятно, что делать, если хотят присвоить груше яблоко...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Вопрос про присваивание объектов
От: rg45 СССР  
Дата: 26.04.11 04:39
Оценка: 3 (2)
Здравствуйте, MasterZiv, Вы писали:

MZ>On 24.04.2011 20:14, Lorenzo_LAMAS wrote:


>> Это демонстрация того, что твое утверждение про невозможность динамического

>> полиморфизма для оператора присваивания — не всегда верно. Полиморфизм есть.
>> Динамический.

MZ>А так -- нормально, полный динамический полиморфизм.


С этим нужно быть поаккуратнее, чтоб не получать сюрпризы.

Пример:

#include <iostream>

class A
{
public:
  virtual A& operator=(const A&) 
  { 
    std::cout << "A::operator=" << std::endl; 
    return *this;
  }
};

class B : public A
{
public:
  virtual B& operator=(const A&)
  { 
    std::cout << "B::operator=" << std::endl; 
    return *this;
  }
};

int main()
{
  B b;
  A& ar = b; 
  B& br = b; 

  ar = A(); //Output: "B::operator="
  b = B(); //Output: "A::operator=" 
}


Обратите внимание на последние строки программы. Когда копирующее присваивание выполняется через ссылку на объект A, вызывается B::operator= — т.е. работает тот самый полиморфизм, как и ожидалось. А когда копирующее присваивание выполняется непосредственно объекту производного класса, то полиморфизм куда-то вдруг "исчезает" и вызывается оператор копирующего присваивания базового класса. А происходит это потому, что оператор присваивания, определенный в производном классе, не является копирующим. Поэтому компилятор вынужден самостоятельно сгенерировать копирующий оператор присваивания, из которого вызывается копирующий оператор присваивания базового класса. Короче говоря, никогда не стоит забывать о том, что далеко не каждый оператор присваивания является копирующим.
--
Не можешь достичь желаемого — пожелай достигнутого.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.