Динамический полиморфизм без указателей на базовый класс.

Тема в разделе "LANGS.C", создана пользователем Antolflash, 31 май 2011.

  1. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Меня терзают смутные сомненья.

    Дык, а ссылки на что? Что мешает создать в абстрактном классе чистые виртуальные методы, принимающие не указатели, а ссылки?
     
  2. Antolflash

    Antolflash New Member

    Публикаций:
    0
    Регистрация:
    14 дек 2008
    Сообщения:
    167
    green
    Нельзя! Где наследование?
    Код (Text):
    1. #pragma pack(1)
    2. struct basewad
    3. {
    4.     virtual bool GetEdge() = 0;
    5.     virtual bool GetMark() = 0;
    6.     virtual bool GetColour_0() = 0;
    7.     virtual bool GetColour_1() = 0;
    8.     virtual void SetEdge(bool what) = 0;
    9.     virtual void SetMark(bool what) = 0;
    10.     virtual void SetColour_0(bool what) = 0;
    11.     virtual void SetColour_1(bool what) = 0;
    12.     //virtual void operator=(basewad &op2) = 0;
    13.     virtual void operator=(bool edge) = 0;
    14.     virtual operator bool() = 0;
    15.     virtual bool operator==(bool isedge) = 0;
    16. };
    17.  
    18. #pragma pack(1)
    19. struct field : public basewad
    20. {
    21.     unsigned Edge : 1;
    22.     unsigned Mark : 1;
    23.     unsigned Colour_1 : 1;
    24.     unsigned Colour_0 : 1;
    25.     bool GetEdge();
    26.     bool GetMark();
    27.     bool GetColour_0();
    28.     bool GetColour_1();
    29.     void SetEdge(bool what);
    30.     void SetMark(bool what);
    31.     void SetColour_0(bool what);
    32.     void SetColour_1(bool what);
    33.     //void operator=(field &op2);
    34.     void operator=(bool edge);
    35.     //field &operator+=(field &op2);
    36.     //field operator*(field &op2);
    37.     //field operator+(field &op2);
    38.     bool operator==(bool isedge);
    39.     operator bool();
    40.     field();
    41. };
    Вот это будет работать. Но в базовом классе нет операторов, которые возвращают или принимают объект класса basewad или field. Ведь и то и другое невозможно!
     
  3. Antolflash

    Antolflash New Member

    Публикаций:
    0
    Регистрация:
    14 дек 2008
    Сообщения:
    167
    Dmitry_Milk
    Ссылка предполагает наличие реального объекта, который затем будет передан по ссылке. Ссылки на абстрактный класс быть не может, как и объекта абстрактного класса!
     
  4. SilentSnowfall

    SilentSnowfall New Member

    Публикаций:
    0
    Регистрация:
    8 фев 2011
    Сообщения:
    27
    Antolflash, это не пробел в языке.

    Само собой разумеется, что невозможно использовать полиморфизм без указателей/ссылок. И пробела в языке никакого нет. Давай исходить из противного - если бы подобное было возможно, то каким образом бы компилятор определял, сколько памяти в стеке нужно выделить/освободить (т.к. объекты, возвращаемые/передаваемые по значению, создаются на стеке), не зная во время компиляции его истинный тип и размер этого типа?

    С операторами, модифицирующими объект (например, operator += ) проблем нет - ты можешь возвращать ссылку на базовый класс, как в следующем посте. Операторы, которые должны создавать новый объект (например, operator+) ты реализовать так, как ты пишешь в первом посте, естественно, не сможешь.
     
  5. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Сыылка на абстрактный - еще как может!
    Код (Text):
    1. class TBase
    2. {
    3.   public:
    4.   virtual int GetValue()=0;
    5.   virtual TBase& operator +=(TBase&)=0;
    6. };
    7.  
    8. class TChild:public TBase
    9. {
    10.   int data;
    11.   public:
    12.   TChild(int init=0);
    13.   int GetValue();
    14.   void SetValue(int);
    15.   TBase& operator +=(TBase& arg);
    16. };
    17.  
    18. TChild::TChild(int init) { data=init; }
    19. int TChild::GetValue() { return data; }
    20. void TChild::SetValue(int newval) { data=newval; }
    21. TBase& TChild::operator += (TBase& arg)
    22. {
    23.   data+=arg.GetValue();
    24.   return *this;
    25. }
    26.  
    27. void some_func()
    28. {
    29.   //...
    30.   TChild a(1);
    31.   TChild b(2);
    32.   b+=a;
    33.   //...
    34. }
    Заметьте! В дочернем классе, для которого вполне реализуемы объекты:
    Код (Text):
    1.   TBase& operator +=(TBase& arg);
    работает
    Код (Text):
    1.   TChild a(1);
    2.   TChild b(2);
    3.   b+=a;
     
  6. Antolflash

    Antolflash New Member

    Публикаций:
    0
    Регистрация:
    14 дек 2008
    Сообщения:
    167
    Dmitry_Milk
    Ок, я тупанул, ссылка на абстрактный ещё как может быть.

    SilentSnowfall
    Вот про это я и создал тему. Хотел удостовериться в этом.

    Всем спасибо, тему можно закрыть.
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Antolflash
    В чём проблема вообще? ^)
     
  8. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Но теоретически можно реализовывать и такие операторы, если внутри них объект создавать в куче, и возвращать ссылку на объект в куче. Просто проблема это не классов, а отсутствия сборщика мусора - надо самому будет отслеживать, чтоб такой объект не утек.
     
  9. Antolflash

    Antolflash New Member

    Публикаций:
    0
    Регистрация:
    14 дек 2008
    Сообщения:
    167
    Dmitry_Milk
    Ну не красиво выходит, не буду заморачиваться, мне до завтра доделать нужно, я забил уже.
     
  10. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Antolflash
    Вот здесь:
    Код (Text):
    1. class Impl : Interface
    Гм... я ведь продемонстрировал, что это возможно. Вы явно одно говорите, а что-то другое подразумеваете.
    Полагаю, Вы хотите, чтобы оператор класса А, принимающий аргументом объект класса P, виртуально перегружалcя таким же оператором производного от А класса В, но принимающим аргументом объект класса Q, производного от P. Это в самом деле невозможно, но Вы можете в классе B определить нужный Вам оператор, в виде адаптера к нормально перегруженному оператору (т.е. принимающему аргументом P).
    Во-вторых, такая перегрузка возможна средствами языка, если речь не об аргументе, а о возвращаемом значении. См. covariant return types.
     
  11. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Antolflash

    Ты еще вот что путаешь. Мол нельзя создать объект в классе которого есть виртуальные функции. Это не так. Правильно вот так: объект создать можно, но он обязательно должен быть частью объекта, в котором эти функции таки реализованы. То есть, если B является наследником "интерфейса" A, то объект класса B содержит в себе объект класса A, и следовательно объект класса A существует. И через указатель или ссылку на объект класса B можно посмотреть как на объект класса A.

    Код (Text):
    1. class A { };
    2. class B : public A { };
    3.  
    4. B b;
    5. A& a = b;
     
  12. Antolflash

    Antolflash New Member

    Публикаций:
    0
    Регистрация:
    14 дек 2008
    Сообщения:
    167
    Очень верное замечание.
    Вы меня простите, дальнейшее обсуждение почитаю уже послезавтра.