Особенности наследования
От: Kingofastellarwar Украина  
Дата: 03.01.09 20:24
Оценка:
Имеем:


class IComponent
{
    virtual void    CommonMethod()=0;
};

class Component/* : public IComponent - есть/нет на результат не влияет */
{
    void CommonMethod()
    {
        ...
    }
};

class IFrame : public IComponent
{
    virtual void    SpecificMethod()=0;
};

class Frame : public Component, public IFrame
{
    void SpecificMethod()
    {
        ...
    }
};


error C2259: 'Frame' : cannot instantiate abstract class
due to following members:
'void IComponent::CommonMethod(bool)' : is abstract

Народ, как такое разруливать? Вроде ничего сверхестественного не делаю
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re: Особенности наследования
От: frogkiller Россия  
Дата: 03.01.09 20:42
Оценка: 3 (1)
Здравствуйте, Kingofastellarwar, Вы писали:

K>Народ, как такое разруливать? Вроде ничего сверхестественного не делаю


У тебя IComponent два раза включается, надо использовать виртуальное наследование.
Типа такого:

K>
K>class IComponent
K>{
K>    virtual void    CommonMethod()=0;
K>};

K>class Component : public virtual IComponent
K>{
K>    void CommonMethod()
K>    {
K>        ...
K>    }
K>};

K>class IFrame : public virtual IComponent
K>{
K>    virtual void    SpecificMethod()=0;
K>};

K>class Frame : public Component, public IFrame
K>{
K>    void SpecificMethod()
K>    {
K>        ...
K>    }
K>};

K>
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re: Особенности наследования
От: Alexander G Украина  
Дата: 03.01.09 20:49
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>Народ, как такое разруливать? Вроде ничего сверхестественного не делаю


Делаешь. Без ": public IComponent" — не перекрываешь виртуальную функцию, с этим — имеешь две базы IComponent с перекрытым CommonMethod только в одном.
Варианты:
1. Пересмотреть дизайн
2. Сделать IComponent виртуальным базовым классом — в обоих наследованиях : public virtual IComponent
3. Применить шаблоны. Например, сделать Component шаблонным, template<class T> class Component : public T {}; class Frame : public Component<IFrame> {}; Или вообще всё сделать на CRTP базах (WTL-way)
Русский военный корабль идёт ко дну!
Re[2]: Особенности наследования
От: Kingofastellarwar Украина  
Дата: 03.01.09 22:52
Оценка:
Здравствуйте, Alexander G, Вы писали:

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


K>>Народ, как такое разруливать? Вроде ничего сверхестественного не делаю


AG>Делаешь. Без ": public IComponent" — не перекрываешь виртуальную функцию, с этим — имеешь две базы IComponent с перекрытым CommonMethod только в одном.

AG>Варианты:
AG>1. Пересмотреть дизайн
AG>2. Сделать IComponent виртуальным базовым классом — в обоих наследованиях : public virtual IComponent
AG>3. Применить шаблоны. Например, сделать Component шаблонным, template<class T> class Component : public T {}; class Frame : public Component<IFrame> {}; Или вообще всё сделать на CRTP базах (WTL-way)


пасиба мужики, про виртуал я тупо забыл, а вообще нада подумать...инетересно как такое решают на практике? мне кажется такое нужно довольно часто: базовый интерфейс для кастомных интерфейсов и соответствующий базовый класс для кастомных классов реализующие эти кастомные интерфейсы.
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[3]: Особенности наследования
От: Alexander G Украина  
Дата: 03.01.09 23:04
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>инетересно как такое решают на практике? мне кажется такое нужно довольно часто: базовый интерфейс для кастомных интерфейсов и соответствующий базовый класс для кастомных классов реализующие эти кастомные интерфейсы.


Я вроде как назвал все способы решения, с которыми сталкивался.
Виртуальное наследование плюс доминирование — сложная штука. И имеет рантайм оверхед
Автор: Alexander G
Дата: 27.06.08
 и по памяти и по времени.
Сделать всё на шаблонах — полиморфизм будет чисто статическим. И опять таки сложная штука.
Русский военный корабль идёт ко дну!
Re[4]: Особенности наследования
От: Kingofastellarwar Украина  
Дата: 03.01.09 23:26
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Я вроде как назвал все способы решения, с которыми сталкивался.

AG>Виртуальное наследование плюс доминирование — сложная штука. И имеет рантайм оверхед<br />
<span class='lineQuote level1'>AG&gt;</span>
Автор: Alexander G
Дата: 27.06.08
 и по памяти и по времени.

AG>Сделать всё на шаблонах — полиморфизм будет чисто статическим. И опять таки сложная штука.

та не, я имел ввиду как можно архитектуру поменять, чтобы эту проблему можно было вообще избежать. и желательно без шаблонных извратов
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[3]: Особенности наследования
От: frogkiller Россия  
Дата: 04.01.09 06:33
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>пасиба мужики, про виртуал я тупо забыл, а вообще нада подумать...инетересно как такое решают на практике? мне кажется такое нужно довольно часто: базовый интерфейс для кастомных интерфейсов и соответствующий базовый класс для кастомных классов реализующие эти кастомные интерфейсы.


Имхо, каждый раз изобретают свой велосипед согласно вкусам конкретного разработчика

Вот здесь
Автор: frogkiller
Дата: 30.12.08
я попробовал предложить прототип общего решения, основанного как раз на шаблонах и виртуальном наследовании, но народ как-то не оценил
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[5]: Особенности наследования
От: Alexander G Украина  
Дата: 04.01.09 08:57
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>та не, я имел ввиду как можно архитектуру поменять, чтобы эту проблему можно было вообще избежать. и желательно без шаблонных извратов


Самое простое — не наследуй реализацию, наследуй только интерфейс.
Русский военный корабль идёт ко дну!
Re[6]: Особенности наследования
От: Kingofastellarwar Украина  
Дата: 04.01.09 10:12
Оценка:
Здравствуйте, Alexander G, Вы писали:

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


K>>та не, я имел ввиду как можно архитектуру поменять, чтобы эту проблему можно было вообще избежать. и желательно без шаблонных извратов


AG>Самое простое — не наследуй реализацию, наследуй только интерфейс.


а общие методы как? делегировать? тогда в каждом классе появится много однострочных одинаковызх методов.
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[7]: Особенности наследования
От: SleepyDrago Украина  
Дата: 04.01.09 10:28
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

AG>>Самое простое — не наследуй реализацию, наследуй только интерфейс.

+1000

K>а общие методы как? делегировать? тогда в каждом классе появится много однострочных одинаковызх методов.


Все познается в сравнении. Ну будет у тебя столько же 3х строчных методов, каждый из которых вызывает цепочку унаследованных и насколько легче будет вносить изменения?
single responsibility principle придумали не для того чтобы меньше бить по клавишам
кстати классная иллюстрация здесь
И между прочим IComponent не далеко ушел от эмфэцэшного CObject и тп это одна сплошная ошибка проектирования
Re[8]: Особенности наследования
От: Kingofastellarwar Украина  
Дата: 04.01.09 10:55
Оценка:
Здравствуйте, SleepyDrago, Вы писали:

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


AG>>>Самое простое — не наследуй реализацию, наследуй только интерфейс.

SD>+1000

K>>а общие методы как? делегировать? тогда в каждом классе появится много однострочных одинаковызх методов.


SD>Все познается в сравнении. Ну будет у тебя столько же 3х строчных методов, каждый из которых вызывает цепочку унаследованных и насколько легче будет вносить изменения?

SD>single responsibility principle придумали не для того чтобы меньше бить по клавишам
SD>кстати классная иллюстрация здесь
SD>И между прочим IComponent не далеко ушел от эмфэцэшного CObject и тп это одна сплошная ошибка проектирования

ну при наследовании у меня не будет дублирования одного и того же, потому что оно будет описано в базовом и унаследовано остальными т.е. я не понял какие 3х строчные методы имеются ввиду.
или это сейчас считается плохим тоном?

а single responsibility principle это конечно правильно, но так же ж можно к чистому Си скатиться а вообще можете пример показать как бы вы в данном случае делегировали вместо наследования?

а в чем беда CObject? я не в курсе. да и у меня самого есть такие базовые классы и не вижу в этом проблемы, как раз очень удобно.
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[9]: Особенности наследования
От: SleepyDrago Украина  
Дата: 04.01.09 12:18
Оценка: +1
Здравствуйте, Kingofastellarwar,

Написал кучу слов — потом подумал и стер
"Пишите unit tests".

зы если все таки интересуют долгие объяснения, то нет смысла их тут выписывать тк есть книжки, на которые стоит ссылаться. Например в "Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin Series)" сравните 6ю главу и 10ю.
Re[10]: Особенности наследования
От: DmitryShm Россия  
Дата: 04.01.09 12:22
Оценка:
Здравствуйте, SleepyDrago, Вы писали:

SD>зы если все таки интересуют долгие объяснения, то нет смысла их тут выписывать тк есть книжки, на которые стоит ссылаться. Например в "Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin Series)" сравните 6ю главу и 10ю.


Согласен, ведь архитектура вообще сильно зависит от требований к программе и коду.
Re: Особенности наследования
От: Kingofastellarwar Украина  
Дата: 04.01.09 14:58
Оценка: :)
Гы, а в C# вообще такой проблемы нет...из-за того что там множественного наследования нет?


    interface IComponent
    {
        void        SetName(string name);
    }

    class Component : IComponent
    {
        string _name;
        
        public void SetName(string name)
        {
            _name = name;
        }
    }

    interface IFrame : IComponent
    {
        void    SetSize(int t);
    }


    class Frame : Component, IFrame
    {
        public void SetSize(int t)
        {
        
        }
    }
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re: Особенности наследования
От: Kingofastellarwar Украина  
Дата: 04.01.09 20:42
Оценка:
народ, я так понимаю вы предлагаете этот вариант:
(просто хочу знать как сейчас модно делать

class IComponent
{
    virtual void    CommonMethod()=0;
};

class Component /* никого не реализуем*/
{
    void CommonMethod()
    {
        ...
    }
};

class IFrame : public IComponent
{
    virtual void    SpecificMethod()=0;
};

class Frame : public Component, public IFrame
{

    void CommonMethod()
    {
        Component::CommonMethod();
    }

    void SpecificMethod()
    {
        ...
    }
};
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[2]: Особенности наследования
От: Alexander G Украина  
Дата: 04.01.09 23:17
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>Гы, а в C# вообще такой проблемы нет...из-за того что там множественного наследования нет?


И в Delphi тоже из-за того что множественного наследования реализации нет, и интерфейс там это не класс.
Русский военный корабль идёт ко дну!
Re[2]: Особенности наследования
От: Alexander G Украина  
Дата: 04.01.09 23:23
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>народ, я так понимаю вы предлагаете этот вариант:


K>class Frame : public Component, public IFrame
K>{
K>
K>    void CommonMethod()
K>    {
K>        Component::CommonMethod();
K>    }

K>    void SpecificMethod()
K>    {
K>        ...
K>    }
K>};


Замени наследование от Component композицией. Наследование реализации не модно

class Frame : public IFrame
{
   Component component_;

   void CommonMethod()
   {
      return component_.CommonMethod();
   }

   void SpecificMethod()
   {
        ...
   }
};
Русский военный корабль идёт ко дну!
Re[3]: Особенности наследования
От: Kingofastellarwar Украина  
Дата: 05.01.09 18:24
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Замени наследование от Component композицией. Наследование реализации не модно


AG>
AG>class Frame : public IFrame
AG>{
AG>   Component component_;

AG>   void CommonMethod()
AG>   {
AG>      return component_.CommonMethod();
AG>   }

AG>   void SpecificMethod()
AG>   {
AG>        ...
AG>   }
AG>};
AG>



Мож тогда вообще вот так делать? Народ тут говорит что тоже модно

class Frame : public IFrame
{
   Component component_;


   IComponent * GetComponent()
   {
      return component_;
   }

   void SpecificMethod()
   {
        ...
   }
};
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[4]: Особенности наследования
От: frogkiller Россия  
Дата: 05.01.09 21:36
Оценка: 2 (1)
Здравствуйте, Kingofastellarwar, Вы писали:

K>Мож тогда вообще вот так делать? Народ тут говорит что тоже модно


K>
K>class Frame : public IFrame
K>{
K>   Component component_;

K>
K>   IComponent * GetComponent()
K>   {
K>      return component_;
K>   }

K>   void SpecificMethod()
K>   {
K>        ...
K>   }
K>};
K>


Так будет нарушаться law of demeter
Автор: Odi$$ey
Дата: 18.05.07
.
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re: Особенности наследования
От: johny5 Новая Зеландия
Дата: 05.01.09 23:47
Оценка: 3 (1)
Здравствуйте, Kingofastellarwar, Вы писали:

K>Имеем:



K>
K>class Component : public virtual IComponent
K>{
K>    void CommonMethod()
K>    {
K>        ...
K>    }
K>};

K>class IFrame : public virtual IComponent
K>{
K>    virtual void    SpecificMethod()=0;
K>};

K>class Frame : public Component, public IFrame
K>{
K>    ...
K>};
K>


K>error C2259: 'Frame' : cannot instantiate abstract class


K>Народ, как такое разруливать? Вроде ничего сверхестественного не делаю


Если вы хотите замещать виртуальный метод в базовом интерфейсе из первой иерархии наследования в другой, параллельной иерархии наследования, тогда базовый интерфейс в обоих иерархиях должен наследоваться виртуально. Тогда интерфейс превратиться в единый базовый класс (т.е. интерфейс будет присутствовать лишь единожды в объекте Frame-а) и виртуальные фукнции будут замещаться так как вы хотите. Правда в студии появиться другой warning, C4250: 'Frame' : inherits 'Component::Component::CommonMethod' via dominance, который лишь говорит о том что произошло нечто нетривиальное: функция была отнаследована из параллельной иерархии и возможно это не то что вы хотите.
Re: Особенности наследования
От: NLyapin Россия https://architecture-cleaning.ru/
Дата: 11.01.09 07:31
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>Народ, как такое разруливать? Вроде ничего сверхестественного не делаю


Про виртуальные функции написали уже. Однако при простом совпадении имен функций:

class IComponent
{
    virtual void CommonMethod()=0;
};

class Component
{
public:
    void CommonMethod()
    {
        cout<<"Component::CommonMethod()"<<endl;
    }
};

class IFrame : public IComponent
{
    virtual void    SpecificMethod()=0;
};

class Frame : public Component, public IFrame
{
public:    
    void CommonMethod();
    void SpecificMethod()
    {
        cout<<"Frame::SpecificMethod()"<<endl;
    }
};

void Frame::CommonMethod()
{
    cout<<"Frame::CommonMethod()"<<endl;
}


Используем:

    Frame frm;
    frm.CommonMethod();
    frm.Component::CommonMethod();
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.