Расскажите, почему наследование здесь 'misused'
От: _Winnie Россия C++.freerun
Дата: 12.01.06 17:48
Оценка:
предположим, я часто делаю какую-то операцию с std::string, и хотел бы к нему добавить методы.
Можно это сделать так:

struct my_string: public std::string //забудем пока про basic_string<C, T, A>, вопрос про misused 
{
//повторяю конструкторы std::string
...
//добавляю свои 'удобные методы'
};

template <class T>
struct my_vector: std::vector<T>
{
};


какие причины есть считать это злом? Нутром чую, что это путь в ад, но пока не вижу конкретных плохих вещей. Едиственное что, вижу проблему когда кто-то захочет вдруг передать std::string в функцию, которая принимает my_string.
Все книжки пишут, естли можете сделать операцию на объектом свободной функцией, а не методом, то лучше методом. Я с этим согласен.
Хотелось бы точно понять, какие грабли есть вот в таком наследовании. (Предположим, что в проекте используется только один такой наследник, и других библиотек, которые так расширили строки, нет)
Собственно — это вторая проблема — когда каждая либа начиная клепать свой такой свой string. предположим, что она одна и основная в проекте.
Перечислите, пожалуйста, как можно больше бяк, почему такое наследование некошерно. ^_^

Спасибо.

PS. Наверное, я не прочитал какую-то книжку. Но протелепатировал себе мысль из неё
Правильно работающая программа — просто частный случай Undefined Behavior
Re: Расскажите, почему наследование здесь 'misused'
От: Июнь  
Дата: 12.01.06 18:13
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>PS. Наверное, я не прочитал какую-то книжку. Но протелепатировал себе мысль из неё


В той книжке было написано, что деструкторы стандартных контейнеров не виртуальны и что наследование — 2-ая по силе зависимость в C++.
Re[2]: Расскажите, почему наследование здесь 'misused'
От: Константин Ленин  
Дата: 12.01.06 18:20
Оценка:
Здравствуйте, Июнь, Вы писали:

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


_W>>PS. Наверное, я не прочитал какую-то книжку. Но протелепатировал себе мысль из неё


И>В той книжке было написано, что деструкторы стандартных контейнеров не виртуальны и что наследование — 2-ая по силе зависимость в C++.


Добавлю, что некоторые(Саттер) считают, что если можно метод сделать не членом класса, то лучше его не делать членом класса. Кому как нравится.
Ну и плюс невиртуальность деструкторов. Хотя при осторожном использовании...)
Re[3]: Расскажите, почему наследование здесь 'misused'
От: jazzer Россия Skype: enerjazzer
Дата: 12.01.06 18:50
Оценка:
Здравствуйте, Константин Ленин, Вы писали:

КЛ>Добавлю, что некоторые(Саттер) считают, что если можно метод сделать не членом класса, то лучше его не делать членом класса. Кому как нравится.


Мейерс. Хотя, может, и Саттер тоже.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Расскажите, почему наследование здесь 'misused'
От: _Winnie Россия C++.freerun
Дата: 12.01.06 19:57
Оценка:
Здравствуйте, Июнь, Вы писали:

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


_W>>PS. Наверное, я не прочитал какую-то книжку. Но протелепатировал себе мысль из неё


И>В той книжке было написано, что деструкторы стандартных контейнеров не виртуальны

Да-да-да. Я как раз собирался завести my_string на хипе, потом откастовать его в std::string*, а потом сделать ему delete. ИМХО, это маловероятно (в основном, первый пункт)

> что наследование — 2-ая по силе зависимость в C++.

Ну, жуть. Расширенный стринг зависит от стандартного. Афигеть.

Можно конкретней, где такое наследование выйдет боком? А не общие слова.
Правильно работающая программа — просто частный случай Undefined Behavior
Re: Расскажите, почему наследование здесь 'misused'
От: _DAle_ Беларусь  
Дата: 12.01.06 20:05
Оценка: 1 (1) +1
Здравствуйте, _Winnie, Вы писали:

[skipped]

_W>PS. Наверное, я не прочитал какую-то книжку. Но протелепатировал себе мысль из неё


Альтернативное мнение
Автор: Андрей Тарасевич
Дата: 25.10.03
Re[4]: Расскажите, почему наследование здесь 'misused'
От: _DAle_ Беларусь  
Дата: 12.01.06 20:08
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Константин Ленин, Вы писали:


КЛ>>Добавлю, что некоторые(Саттер) считают, что если можно метод сделать не членом класса, то лучше его не делать членом класса. Кому как нравится.


J>Мейерс. Хотя, может, и Саттер тоже.


Ага, Саттер с ним на пару.
Re: Расскажите, почему наследование здесь 'misused'
От: _Winnie Россия C++.freerun
Дата: 12.01.06 20:44
Оценка:
Здравствуйте, _Winnie, Вы писали:


!
!
!
!
!

_W>Все книжки пишут, естли можете сделать операцию на объектом свободной функцией, а не методом, то лучше методом. Я с этим согласен.

ИЗВИНИТЕ!
Я хотел написать ровно наобороот — "... то лучше свободной функцией."

!
!
!
!
!
!
Правильно работающая программа — просто частный случай Undefined Behavior
Re: Расскажите, почему наследование здесь 'misused'
От: odisseyLM  
Дата: 12.01.06 21:36
Оценка:
Привет

Пока ты не будешь добавлять свои data-member (иначе их срежешь ...), все будет ОК.
Но все рекомендует этого не делать ...
Также не делай свои ф-ии виртуальными (т.к. std::basic_string для этго не предназначен).

Лично я использую обычные глобальные ф-ии в своем namespace
(точнее шаблоны, при этом реализацию с явным инстанцированием помещаю в .cpp-файлы ).
Re: Расскажите, почему наследование здесь 'misused'
От: np9mi7 Россия  
Дата: 12.01.06 22:22
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>предположим, я часто делаю какую-то операцию с std::string, и хотел бы к нему добавить методы.


Используй агрегицию, а не наследование;

Агрегируй std::string в my_string, реализуй полную совместимость с std::string (конструктор, оператор присваивания и приведение типа), потом "вытащи" в public секцию все методы std::string;

_W>Да-да-да. Я как раз собирался завести my_string на хипе, потом откастовать его в std::string*, а потом сделать ему delete. ИМХО, это маловероятно (в основном, первый пункт)


Зачем хранить в "хипе" std::string и my_string, если в std::string нет виртуальных функций?

ps: вариант с глобальными функциями в отдельном namespace, на мой взгляд самый предпочтительный;
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re[2]: Расскажите, почему наследование здесь 'misused'
От: FreshMeat Россия http://www.rsdn.org
Дата: 12.01.06 22:32
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Все книжки пишут, естли можете сделать операцию на объектом свободной функцией, а не методом, то лучше свободной функцией.

Имхо, лучше смотреть на предметную область и плясать от нее. Примеры методов, которые не смотря на некоторую избыточность интерфейса, смотрятся вполне органично, легко найти в STL — size() (для вектора), is_empty() и т.д..
Хорошо там, где мы есть! :)
Re[2]: Расскажите, почему наследование здесь 'misused'
От: Чипсет Россия http://merlinko.com
Дата: 13.01.06 05:11
Оценка:
Здравствуйте, np9mi7, Вы писали:

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


_W>>предположим, я часто делаю какую-то операцию с std::string, и хотел бы к нему добавить методы.


N>Используй агрегицию, а не наследование;


N>Агрегируй std::string в my_string, реализуй полную совместимость с std::string (конструктор, оператор присваивания и приведение типа), потом "вытащи" в public секцию все методы std::string;


Я правильно понял что ты предлагаешь просто взять все-те функции что есть в std::string и скопипастить их в my_string?
_W>>Да-да-да. Я как раз собирался завести my_string на хипе, потом откастовать его в std::string*, а потом сделать ему delete. ИМХО, это маловероятно (в основном, первый пункт)

N>Зачем хранить в "хипе" std::string и my_string, если в std::string нет виртуальных функций?

Насколько я понял, предполагаеться использование переменной как библиотекой _Winnie (которая знает о my_string) так и сторонней библиотекой которая и понятия не имеет о каких-то там my_string'ах..

N>ps: вариант с глобальными функциями в отдельном namespace, на мой взгляд самый предпочтительный;

... либо отдельным классом наподобие StrHelper
"Всё что не убивает нас, делает нас сильнее..."
Re[3]: Расскажите, почему наследование здесь 'misused'
От: np9mi7 Россия  
Дата: 13.01.06 06:08
Оценка:
Здравствуйте, Чипсет, Вы писали:

Ч>Я правильно понял что ты предлагаешь просто взять все-те функции что есть в std::string и скопипастить их в my_string?


Нет, и имел ввиду это:
#include <string>

/// ...

class my_string
{
        /// ...
        std::string    m_sString;
        /// ...
    public:
    
    /// ...
    
    std::string::value_type * c_str () const
    {
        return m_sString.c_str ();
    }
    
    /// ...
};


N>>Зачем хранить в "хипе" std::string и my_string, если в std::string нет виртуальных функций?

Ч>Насколько я понял, предполагаеться использование переменной как библиотекой _Winnie (которая знает о my_string) так и сторонней библиотекой которая и понятия не имеет о каких-то там my_string'ах..

Я же говорю — реализуй полную совместимость с std::string (конструктор, оператор присваивания и приведение типа);
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re[4]: Расскажите, почему наследование здесь 'misused'
От: Чипсет Россия http://merlinko.com
Дата: 13.01.06 06:34
Оценка:
Здравствуйте, np9mi7, Вы писали:

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


Ч>>Я правильно понял что ты предлагаешь просто взять все-те функции что есть в std::string и скопипастить их в my_string?


N>Нет, и имел ввиду это:

А не гемморой ли?
N>>>Зачем хранить в "хипе" std::string и my_string, если в std::string нет виртуальных функций?
Ч>>Насколько я понял, предполагаеться использование переменной как библиотекой _Winnie (которая знает о my_string) так и сторонней библиотекой которая и понятия не имеет о каких-то там my_string'ах..

N>Я же говорю — реализуй полную совместимость с std::string (конструктор, оператор присваивания и приведение типа);


class A //std::string
{
    public:
    void bI() {};
};
class B //my_string
{
private:
A _a;
public:
void bI() {
    _a.bI(); //гемморой
}
};
 //левая функция левой библиотеки
void foo(A *a)
{
}
//где-то в глубинах кода
void bar()
{
    B *b = new B();
    foo(b); //обломись моя черешня
}
"Всё что не убивает нас, делает нас сильнее..."
Re[2]: Расскажите, почему наследование здесь 'misused'
От: Cyberax Марс  
Дата: 13.01.06 08:16
Оценка:
np9mi7 wrote:
> Используй агрегицию, а не наследование;
> Агрегируй /*std::string*/ в /*my_string*/, реализуй полную совместимость
> с /*std::string*/ (конструктор, оператор присваивания и приведение
> типа), потом "вытащи" в /*public*/ секцию все методы /*std::string*/;
Их там около 80.

> Зачем хранить в "хипе" /*std::string*/ и /*my_string*/, если в

> /*std::string*/ нет виртуальных функций?
Для быстрой передачи, например. Или из одного потока в другой передать.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re: Расскажите, почему наследование здесь 'misused'
От: sadomovalex Россия http://sadomovalex.blogspot.com
Дата: 13.01.06 09:43
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>PS. Наверное, я не прочитал какую-то книжку. Но протелепатировал себе мысль из неё


Exceptional C++ Style Г. Саттера. Задачи с 37 по 40
"Что не завершено, не сделано вовсе" Гаусс
Re[3]: Расскажите, почему наследование здесь 'misused'
От: Июнь  
Дата: 13.01.06 10:59
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>>>PS. Наверное, я не прочитал какую-то книжку. Но протелепатировал себе мысль из неё

...
>> что наследование — 2-ая по силе зависимость в C++.
_W>Ну, жуть. Расширенный стринг зависит от стандартного. Афигеть.
У стандартной строки стандартный только интерфейс, но не реализация.
Я могу привести пример, когда это будет "афигеть". Если ты пишешь статическую/динамическую библиотеку и твой стринг попадает во внешний интерфейс библиотеки. Библиотека собрана и используется. Потом появляется у этой библиотеки клиент, который собран с обновленной версией std::string...
Если от зависимости избавиться, то проблем не будет.

В данном же случае, даже если ты и захочешь уменьшить зависимость, то если extern для шаблонов не работает (а в той книжке написано, что он вероятнее всего не работает), то придется извращаться: хранить указатель на string + forward typedef declaration.

_W>Можно конкретней, где такое наследование выйдет боком? А не общие слова.


"общие слова" — это попытка записать ту мысль, которую ты "протелепатировал", но не смог сформулировать.
Re: Расскажите, почему наследование здесь 'misused'
От: Шахтер Интернет  
Дата: 13.01.06 11:03
Оценка:
Здравствуйте, _Winnie, Вы писали: ...

На мой взгляд, идеальным решением проблемы было бы такое.


mixin : string 
 {
  void method1()
   {
    ...
   }
   
  void method2() const
   {
    ...
   }
 }
 
string str;

str.method1(); 
str.method2();


Современный С++ это не поддерживает. Но можно чуть-чуть менее удобно сделать так.


/* main.cpp */ 

#include <iostream>
#include <string>

using namespace std;

class super_string_ref
 {
   union
    {
     string *str;
     const string *cstr;
    };
   
  public:
  
   super_string_ref(string &str_) { str=&str_; }
   
   super_string_ref(const string &str_) { cstr=&str_; }
   
   void set()
    {
     // Используем str в неконстантных методах
    
     (*str)="SuperString";
    }
    
   void dump() const
    {
     // Используем cstr в константных методах
    
     cout << (*cstr) << endl ;
    }
 };
 
inline super_string_ref super_string(string &str) { return str; }
  
inline const super_string_ref super_string(const string &str) { return str; }
 
/* main() */ 

void fun1(super_string_ref str) 
 {
  str.set();
 }
 
void fun2(const super_string_ref str) 
 {
  str.dump();
 }
 
int main()
 {
  string str="XXX";
  
  fun1(str);
  fun2(str);
  
  string str1="YYY";
  
  super_string(str1).set();
  super_string(str1).dump();
 
  return 0;
 }
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: Расскажите, почему наследование здесь 'misused'
От: CrystaX Россия https://crystax.me/
Дата: 13.01.06 13:32
Оценка:
Здравствуйте, Cyberax, Вы писали:

>> Используй агрегицию, а не наследование;

>> Агрегируй /*std::string*/ в /*my_string*/, реализуй полную совместимость
>> с /*std::string*/ (конструктор, оператор присваивания и приведение
>> типа), потом "вытащи" в /*public*/ секцию все методы /*std::string*/;
C>Их там около 80.

Private наследование + using спасут отца русской демократии.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Расскажите, почему наследование здесь 'misused'
От: c-smile Канада http://terrainformatica.com
Дата: 14.01.06 05:51
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, _Winnie, Вы писали: ...


Ш>На мой взгляд, идеальным решением проблемы было бы такое.


Ш>

Ш>mixin : string 
Ш> {
Ш>  void method1() {  ... }
Ш>  void method2() const { ... }
Ш> }
 
Ш>string str;

Ш>str.method1(); 
Ш>str.method2(); 

Ш>


Ш>Современный С++ это не поддерживает. Но можно чуть-чуть менее удобно сделать так.


А я вот у себя в tiscript сделал внешние методы:

Можно написать так:

function String.method1() { ... }
function String.method2() { ... }


и стандартный String класс приобретет эти методы.

После этих деклараций можно сказать например такое:

"Привет Шахтер!".method();



Собственно таким динамическим образом можно образовать любой класс:

var MyClass = {};
function MyClass.method1() { ... }
function MyClass.method2() { ... }


А современный C++ этого не поддерживает... А мне нравится...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.