Re[4]: Расширение С++
От: IAZ http://iaz.simb.ru
Дата: 24.03.03 15:41
Оценка: 18 (4)
Здравствуйте, Denwer, Вы писали:

D>Здравствуйте, Аноним, Вы писали:


D>

А>>Т.е., хотелось бы иметь средства, которые позволят легко расширять (возможно, чужие) библиотеки (для своих нужд) причем, так, чтобы эти расширения и сами библиотеки можно было бы легко сопровождать, и, желательно, независимо друг от друга.

А>>Denwer, я правильно понял?


А>>--

А>>Дмитрий

D>ДА ДА ДА


Хороший способ расширения библиотеки классов — это использование оберток.
Например, пусть у нас есть библиотека классов:


class A
{
public:
   void f();
};
class B : public A
{
public:
   void g();
};



и ее требуется расширить одной фукцией void h()


template<class T>
class X
{
public:
   X(T* _a) : a(_a) {}
   void h();
   T* operator->()
   {
     return a;
   }
private:
   T* a;
};


Использовать такой класс-обертку не сложнее чем обычный класс:

X<A> xa(new A);
xa.h();  // вызов X::h()
xa->f(); // вызов A::f()

X<B> xb(new B);
xb.h();  // вызов X::h()
xb->f(); // вызов A::f()
xb->g(); // вызов B::g()



Конечно в этом случае надо знать, что к методам класса X надо обращаться через '.' а к другим через '->' Но неужели это проблема?!

Доступа к закрытым методам классов A & B тоже не получишь.
Зато дешево, надежно и практично.
Кто ищет то всегда найдет!
Re[5]: Расширение С++
От: Аноним  
Дата: 25.03.03 13:26
Оценка: 11 (3)
Здравствуйте, IAZ, Вы писали:

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


D>>Здравствуйте, Аноним, Вы писали:


D>>

А>>>Т.е., хотелось бы иметь средства, которые позволят легко расширять (возможно, чужие) библиотеки (для своих нужд) причем, так, чтобы эти расширения и сами библиотеки можно было бы легко сопровождать, и, желательно, независимо друг от друга.

А>>>Denwer, я правильно понял?


А>>>--

А>>>Дмитрий

D>>ДА ДА ДА


IAZ>Хороший способ расширения библиотеки классов — это использование оберток.


Хороший! Тем не менее, он не всегда срабатывает. Например, если нужно добавить не просто методы, а и члены-данные.

Думаю, что не мешает ввести немного конкретики. Допустим у нас есть класс Figure с методом move(int, int) и классы Square и Circle, которые наследуются от Figure и реализуют move(int, int) по-своему.

class Figure {
private:
   // . . .
public:
   virtual void move(int dx, int dy) =0;
   // . . .
};

class Square: public Figure {
private:
    int left, top, right, bottom;
    // . . .
public:
    virtual void move(int dx, int dy);
    // . . .
};

class Circle: public Figure {
private:
    int cx, cy, radius;
    // . . .
public:
    virtual void move(int dx, int dy);
    // . . .
};


А теперь мы хотим отслеживать перемещения фигур. Скажем, когда какая-нибудь фигура перемещается она посылает сообщения своему подписчику (или подписчикам). Попробуем организовать подписку таким образом:
class MovingSubscriber {
public:
    virtual void beforeMoving(int dx, int dy) =0;
    virtual void afterMoving(int dx, int dy) =0;
};

class FigureWithSubscription: public Figure {
private:
    MovingSubscriber *subscriber;
public:
    virtual void realMove(int dx, int dy) =0;
    virtual void move(int dx, int dy) {
        if(subscriber) subscriber->beforeMoving(dx, dy);
        realMove(dx, dy);
        if(subscriber) subscriber->afterMoving(dx, dy);
    }
    virtual void setSubscriber(MovingSubscriber *s) {
        subscriber = s;
    }
};


Однако, Square и Circle ничего не знают о FigureWithSubscription и поэтому никаких сообщений при своем перемещении никому не посылают. Попробуем сделать так:

template<class T>
class GenericFigureWithSubscription: public T {
private:
    MovingSubscriber *subscriber;
public:
    virtual void move(int dx, int dy) {
        if(subscriber) subscriber->beforeMoving(dx, dy);
        T::move(dx, dy);
        if(subscriber) subscriber->afterMoving(dx, dy);
    }
    virtual void setSubscriber(MovingSubscriber *s) {
        subscriber = s;
    }
};

class SquareWithSubscription: public GenericFigureWithSubscription<Square> {
};

class CircleWithSubscription: public GenericFigureWithSubscription<Circle> {
};


Вроде все нормально. Но следует заметить, что количество дополнительного кода прямо пропорционально количеству прямых наследников от Figure, что не есть хорошо. Но и это еще не все! Данные изменения касаются только объектов, созданных разработчиком, который знает о подписке и знает, что теперь нужно создавать объекты класса SquareWithSubscription а не просто Square. Т.е. подписаться на премещения объектов, которые были созданы где-то в недрах библиотеки невозможно. Для того, чтобы сделать это реальностью, придется делать класс-оболочку, к которому можно будет подписаться и который будет делегировать вызовы реальному объекту.

class WrapperWithSubscription: public Figure {
private:
    Figure *figure;
    MovingSubscriber *subscriber;
public:
    WrapperWithSubscription(Figure *f): figure(f) {}
    virtual void move(int dx, int dy) {
        if(subscriber) subscriber->beforeMoving(dx, dy);
        figure->move(dx, dy);
        if(subscriber) subscriber->afterMoving(dx, dy);
    }
    virtual void setSubscriber(MovingSubscriber *s) {
        subscriber = s;
    }
}


А после этого следить, чтобы все двигали фигуры только через врапперы! Как, оказывается, легко тривиальную задачу превратить в большую неприятность!

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

Впрочем, чтобы немного упростить себе жизнь, придумали аспектно-ориентированное программирование. В частности, задача с перемещениями фигур могла бы решаться при помощи такого аспекта (здесь приведен псевдокод):
aspect FigureSubscrition {
    // добавление в класс Figure член-данное subscriber
    MovingSubscriber *Figure::subscriber;
    // добавление в класс Figure метод setSubscriber
    virtual void Figure::setSubscriber(MovingSubscriber *s) {
        subscriber = s;
    }

    // определение кода, который будет вызываться до и после вызова метода.
    before(Figure *p, int dx, int dy): target(p) && call(void Figure::move(int dx, int dy)) {
        if(p->subscriber) p->subscriber->beforeMoving(dx, dy);
    }
    after(Figure *p, int dx, int dy): target(p) && call(void Figure::move(int dx, int dy)) {
        if(p->subscriber) p->subscriber->afterMoving(dx, dy);
    }
}
Re: Расширение С++
От: WolfHound  
Дата: 24.03.03 16:57
Оценка: 9 (3)
Здравствуйте, Denwer, Вы писали:

Просто библиотеки нужно писать правильно.


Классическая иерархия.
class A{};
class B:public A{};
class C:public B{};
class D:public C{};



Модерновая иерархия.
template <class T>
class Empty{};

class A{};

template <template<class>class T=Empty>
class B:public T<A>{};

template <template<class>class T=Empty>
class C:public B<T>{};

template <template<class>class T=Empty>
class D:public C<T>{};

Теперь если нам нужно расширить функциональность то пишем так
template<class Base>
class E:public Base
{};
typedef D<E> D2;


А если нужно таскать за указатель на промежуточный класс то для этого класса придется сотворить интерфейс. ИМХО не большая плата за большую гипкость.
Хотя если в своем коде то не обязательно. Но лучше завести чтобы небыло мучетельно больно.

Итого:
template <class T>
class Empty{};

class IA{};
class A:public IA{};

class IB{};
template <template<class>class T=Empty>
class B:public T<A>, public IB{};

class IC{};
template <template<class>class T=Empty>
class C:public B<T>, public IC{};

class ID{};
template <template<class>class T=Empty>
class D:public C<T>, public ID{};

class IE{};
template<class Base>
class E:public Base, public IE
{};

int main()
{
    //Можно так
    D<E> de;
    B<E>* be=&de;
    //Можно приводить к интерфейсу...
    //Можно еще что нибудь придумать...
}


ЗЫ Не забываем про виртуальные деструкторы(опущены для краткости).
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Расширение С++
От: Аноним  
Дата: 24.03.03 13:06
Оценка: 12 (1)
Здравствуйте, Sergeem, Вы писали:

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


D>>Привет всем.

D>>Вот у меня какое предложение.
D>>Очень часте приходится например добавлять какуе то функцию, для класса, при этом приходится ее делать либо как член класса, тогда нужно еще переписать все конструкторы и оператор присваивания, либо не как член класса, тогда все протектед данные будут не видны.

S>Вот это я не понял! Зачем переписывать конструкторы, если мы добавляем новую функцию в класс??!


Я тоже не уверен, что понял Denwer'а правильно, но если что, он меня поправит.

Допустим, один разработчик разработал библиотеку классов A, B, C, D... (и, для определенности, класс A является базовым классом иерархии). А другой разработчик решил ее использовать. И все ему в этой библиотеке нравится, но... если бы класс A имел дополнительно еще метод do_something(), который делает очень полезные вещи, было бы совсем супер! Можно конечно сделать свой класс X, который наследуется от A и расширяет функциональность желанным методом do_something(), но классы B, C, D (которые наследуются от A, а не от X) не получат желаемой функциональности. Можно взять исходники библиотеки и добавить этот злосчастный метод прямо в A. Но, по-первых, исходники могут быть недоступны, а во-вторых, первый разработчик может продолжительное время сопровождать свою библиотеку исправляя и добавляя баги и фичи, и с каждым новым релизом библиотеки, второму разработчику приходится заново все добавлять.

Т.е., хотелось бы иметь средства, которые позволят легко расширять (возможно, чужие) библиотеки (для своих нужд) причем, так, чтобы эти расширения и сами библиотеки можно было бы легко сопровождать, и, желательно, независимо друг от друга.

Denwer, я правильно понял?

--
Дмитрий
Расширение С++
От: Denwer Россия  
Дата: 24.03.03 06:48
Оценка: 3 (1)
Привет всем.
Вот у меня какое предложение.
Очень часте приходится например добавлять какуе то функцию, для класса, при этом приходится ее делать либо как член класса, тогда нужно еще переписать все конструкторы и оператор присваивания, либо не как член класса, тогда все протектед данные будут не видны.
Так вот, хорошо бы добавить в С++ такую фичу.
class A
{
..........
}

extend class A
{
//тут методы и данные которые добавляются к классу А
//причем тип доступа такойже как и при наследовании
//тоесть можно добраться до протектед данных
}


Причем мы не вводим нового класса, а это иногда большой плюс если объект создает какая нибудь библиотека, то добавлять функции приходится не как члены класа. Взять ту же MFC, когда нужно дописать новый метод для класса CWnd, экземпляр которого создан самой библиотекой, то начинаешь шаманить.

Какие есть мнения на сей счет???
Re[7]: Расширение С++
От: Дмитро  
Дата: 28.03.03 01:54
Оценка: 3 (1)
Здравствуйте, Артур, Вы писали:


А>Ну предположим ты добавляешь члены-данные, а где-то в глубине MFC код создаёт объект-наследник от CWnd и не знает, что ты добавил новый — член данных, и у CWnd изменился размер, и что тогда?


Действительно как-то нехорошо получается...

Ситуация еще усугубляется тем, что Microsoft могут в следующей версии MFC сами изменить размер CWnd. И весь код, который использует CWnd придется заново перекомпилировать под новую версию. А изменения, возможно, касались просто какого-нибудь приватного поля (которое должно было бы быть глубоко инкапсулировано)! Даже не интерфейса класса!

Впрочем, С++ достаточно гибок, и если работать не с конкретными классами, а с указателями на абстрактные интерфейсы, то можно избежать подобных проблем.

А>Кстати похожая функциональность есть если не ошибаюсь в JavaScript. Там можно во время выполнения добавлять в классы поля. Но это же интерпретируемый язык. В С++ такое сделать будет нелегко.


В С++ много чего можно сделать. Примером, тому может оригинальная идея Вадима, использовать alloca, для выделения памяти для объектов в стеке, размер которых может меняться; и "модерновая иерархия" Андрея WolfHound. Но я не помню, чтобы где-то я встречал что-то подобное, а если бы и встретил, то не сразу бы "догнал", что имеется в виду. Дело в том, что код становится более сложным и неочевидным и без огромных коментариев, зачем это нужно, никак не обойтись.

--
Дмитрий

"Я понимаю, что 2+2=4, но это мне кажется невыносимым." (с) Неврастеник
--
Дмитрий
Re[6]: Расширение С++
От: IAZ http://iaz.simb.ru
Дата: 25.03.03 20:04
Оценка: 2 (1)
Здравствуйте, Аноним, Вы писали:

IAZ>>Хороший способ расширения библиотеки классов — это использование оберток.


А>Хороший! Тем не менее, он не всегда срабатывает. Например, если нужно добавить не просто методы, а и члены-данные.


Почему? Кто запрещает поместить вместе с методом и атрибуты?


template<class T>
class X
{
public:
   X(T* _a) : a(_a) {}
   void h(); // метод
   int k;    // атрибут
   T* operator->()
   {
     return a;
   }
private:
   T* a;
};




А>Думаю, что не мешает ввести немного конкретики. Допустим у нас есть класс Figure с методом move(int, int) и классы Square и Circle, которые наследуются от Figure и реализуют move(int, int) по-своему.

<skip>
А>Вроде все нормально. Но следует заметить, что количество дополнительного кода прямо пропорционально количеству прямых наследников от Figure, что не есть хорошо. Но и это еще не все! Данные изменения касаются только объектов, созданных разработчиком, который знает о подписке и знает, что теперь нужно создавать объекты класса SquareWithSubscription а не просто Square. Т.е. подписаться на премещения объектов, которые были созданы где-то в недрах библиотеки невозможно.

Подобные (со сложной иеррархией и интенсивным использованием полиморфизма) библиотеки классов (не объектов!) создаются для их дальнейшего использования и рассширения другими программистами. Что означает, что внутри этой библиотеки объекты не порождаются. Просто может не быть тех классов от которых можно создать объект. А если и можно то что с ним делать? Вопрос который может разрешить только пользователь этой библиотеки. Может тот который и решил рассширить ее для получения извещения при перемещении фигур. А другим это возможность может и не нужна! Зачем навязывать всем свое мнение о перемещении фигур? А то получается, что написал я графический редактор с использованием обычной библитеки классов (без извещения). А в один прекрасный момент программа стала посылать кому-то какие-то извещения!


А>А после этого следить, чтобы все двигали фигуры только через врапперы!


За кем следить? Подробнее см. выше.

А>Получается, что расширить библиотеку таким образом, каким явно не предусмотрел разработчик этой библиотеки, зачастую крайне трудно, если и вообще возможно.


Вот это действительно так. А может библиотека специально спроектирована не расширяемой!?

А>Впрочем, чтобы немного упростить себе жизнь, придумали аспектно-ориентированное программирование.


За каждым упрощением скрывается море проблем.

А>В частности, задача с перемещениями фигур могла бы решаться при помощи такого аспекта (здесь приведен псевдокод):


С теоретической точки зрения возможно это иногда нужно. Но только при обязательном условии: чтобы можно было это оключать или недопускать распространения на определенные объекты!
Кто ищет то всегда найдет!
Re[6]: Расширение С++
От: Артур Россия  
Дата: 26.03.03 13:07
Оценка: 2 (1)
Ну предположим ты добавляешь члены-данные, а где-то в глубине MFC код создаёт объект-наследник от CWnd и не знает, что ты добавил новый — член данных, и у CWnd изменился размер, и что тогда?

Кстати похожая функциональность есть если не ошибаюсь в JavaScript. Там можно во время выполнения добавлять в классы поля. Но это же интерпретируемый язык. В С++ такое сделать будет нелегко.
... << RSDN@Home 1.0 beta 6a >>
Re[7]: Ну это просто
От: lboss Россия  
Дата: 27.03.03 10:33
Оценка: 2 (1)
Здравствуйте, Артур, Вы писали:

А>Ну предположим ты добавляешь члены-данные, а где-то в глубине MFC код создаёт объект-наследник от CWnd и не знает, что ты добавил новый — член данных, и у CWnd изменился размер, и что тогда?


А>Кстати похожая функциональность есть если не ошибаюсь в JavaScript. Там можно во время выполнения добавлять в классы поля. Но это же интерпретируемый язык. В С++ такое сделать будет нелегко.


Можно просто сделать sizeof статическим мембером класса:

class A
{
public:
static size_t sizeofThis;
};


Испрользование:
A a; =>  A& a= *(A*)alloca(A::sizeofThis);
С уважением Вадим.
Re[10]: Ну это зря...
От: lboss Россия  
Дата: 28.03.03 10:26
Оценка: 2 (1)
Здравствуйте, Дмитро, Вы писали:

L>>Реально это не плохо используется в Object-C++

Д>Что это? Дай ссылку или другой какой источник.

Это то на чем на Mac OS X программают — это надстройка над C (Object-C) и C++ (Object-C++). http://developer.apple.com/techpubs/macosx/Cocoa/ObjectiveC/index.html
С уважением Вадим.
Re: Расширение С++
От: Аноним  
Дата: 24.03.03 08:11
Оценка:
Это получается, что ты хочешь иметь объекты А переменного размера?
Т.е.
class A{
public:
   virtual void Fun(){}
private:
   double d;
};
A a; //sizeof a == 16
extended class A{
public:
   void Fun1(){
      i = 10; 
   }
private:
  int i;
};



void g(){ //sizeof a == 24 ???????
   a.Fun1(); ?????
}


А может лучше о наследовании подумать?
Re[2]: Расширение С++
От: Denwer Россия  
Дата: 24.03.03 08:24
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А может лучше о наследовании подумать?


Ну в начале можн хотябы вообще запрятить объявление виртуальных методов.
А вообще над этим тоже можно подумать еще. Ну например(первое что пришло в голову) иметь не одну виртуальную таблицу а несколько, причем последний элемент этой таблицы будет указатель на следующую. Конечно работать будет медленнее, но это решение так скажем "в лоб", и что стоит ЕЩЕ подумать.

О наследовании думай сколько хочешь, но если ты объект не создаешь то никакое наследование не поможет. Только обычную функцию писать, которая конечно не доберется до протектед методов.
Re: Расширение С++
От: Sergeem Израиль  
Дата: 24.03.03 09:23
Оценка:
Здравствуйте, Denwer, Вы писали:

D>Привет всем.

D>Вот у меня какое предложение.
D>Очень часте приходится например добавлять какуе то функцию, для класса, при этом приходится ее делать либо как член класса, тогда нужно еще переписать все конструкторы и оператор присваивания, либо не как член класса, тогда все протектед данные будут не видны.

Вот это я не понял! Зачем переписывать конструкторы, если мы добавляем новую функцию в класс??!

Может быть автор имеет желание скрыть реализацию класса, так чтобы ее не было видно в интерфейсном хедере? Тогда надо воспользоваться pimpl-ом.
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
Re[2]: Расширение С++
От: Denwer Россия  
Дата: 24.03.03 09:36
Оценка:
Здравствуйте, Sergeem, Вы писали:

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


D>>Привет всем.

D>>Вот у меня какое предложение.
D>>Очень часте приходится например добавлять какуе то функцию, для класса, при этом приходится ее делать либо как член класса, тогда нужно еще переписать все конструкторы и оператор присваивания, либо не как член класса, тогда все протектед данные будут не видны.

S>Вот это я не понял! Зачем переписывать конструкторы, если мы добавляем новую функцию в класс??!


Мож я неправельно выразился: не переписывать реализацию конструкторов, а написать свои конструкторы которые вызывают конструкторы базового класса. В С++ не наследуются конструкторы и оператор присваивания. Или я уже отстал от жизни настолько сильно?

S>Может быть автор имеет желание скрыть реализацию класса, так чтобы ее не было видно в интерфейсном хедере? Тогда надо воспользоваться pimpl-ом.


Чем-чем?
Re[3]: Расширение С++
От: Znow  
Дата: 24.03.03 09:57
Оценка:
Здравствуйте, Denwer, Вы писали:

D>В С++ не наследуются конструкторы и оператор присваивания.


Операторы присваивания наследуются (но по умолчанию их имена скрыты).
Re: Расширение С++
От: Аноним  
Дата: 24.03.03 09:57
Оценка:
Здравствуйте, Denwer, Вы писали:

http://www.eclipse.org/aspectj/
http://www.aspectc.org/
Может, это то, что ты ищешь?

--
Дмитрий
Re: Расширение С++
От: FatZorro  
Дата: 24.03.03 10:43
Оценка:
Здравствуйте, Denwer, Вы писали:

D>Привет всем.

D>Вот у меня какое предложение.
D>Очень часте приходится например добавлять какуе то функцию, для класса, при этом приходится ее делать либо как член класса, тогда нужно еще переписать все конструкторы и оператор присваивания, либо не как член класса, тогда все протектед данные будут не видны.
D>Так вот, хорошо бы добавить в С++ такую фичу.

D>class A

D>{
D>..........
D>}

D>extend class A


А почему нельзя добавить в класс дружественную функцию? Может я чего не понял?
Т.е. понядобился тебе в классе новый метод, взял и добавил описание ее как дружественной....

PS Хотя косяк! ClassName.Method() так то не получится
Re[2]: Расширение С++
От: Denwer Россия  
Дата: 24.03.03 11:50
Оценка:
Здравствуйте, FatZorro, Вы писали:


FZ>А почему нельзя добавить в класс дружественную функцию? Может я чего не понял?

FZ>Т.е. понядобился тебе в классе новый метод, взял и добавил описание ее как дружественной....

FZ>PS Хотя косяк! ClassName.Method() так то не получится


В основном то реч идет не о моих классах. И что мне взять чужие хедеры и добавить туда строчку с дружественным объявлением. Если бы это мои классы и я мог бы это сделать, то все же я бы не морочил себе голову и сделал наследование.
Re[3]: Расширение С++
От: Denwer Россия  
Дата: 24.03.03 13:54
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Т.е., хотелось бы иметь средства, которые позволят легко расширять (возможно, чужие) библиотеки (для своих нужд) причем, так, чтобы эти расширения и сами библиотеки можно было бы легко сопровождать, и, желательно, независимо друг от друга.


А>Denwer, я правильно понял?


А>--

А>Дмитрий

ДА ДА ДА
Re: Расширение С++
От: Chorkov Россия  
Дата: 24.03.03 14:57
Оценка:
Здравствуйте, Denwer, Вы писали:

D>Привет всем.

D>Вот у меня какое предложение.
D>Очень часте приходится например добавлять какуе то функцию, для класса, при этом приходится ее делать либо как член класса, тогда нужно еще переписать все конструкторы и оператор присваивания, либо не как член класса, тогда все протектед данные будут не видны.
D>Так вот, хорошо бы добавить в С++ такую фичу.

D>class A

D>{
D>..........
D>}

D>extend class A

D>{
D>//тут методы и данные которые добавляются к классу А
D>//причем тип доступа такойже как и при наследовании
D>//тоесть можно добраться до протектед данных
D>}

D>Причем мы не вводим нового класаа, а это иногда большой плюс если объект создает какая нибудь библиотека, то добавлять функции приходится не как члены класа. Взять ту же MFC, когда нужно дописать новый метод для класса CWnd, экземпляр которого создан самой библиотекой, то начинаешь шаманить.


D>Какие есть мнения на сей счет???



А такли нужено оформлять собственную функцию в виде метода класса?
На основе стати http://www.softcraft.ru/coding/sm/sm01.shtml ,
можносказать, что добавление ее как функции, рабьотающей
только с открытыми методами класса-предпочтительние.
С другой стороны, на основании материалов обсуждения: http://www.rsdn.ru/Forum/?mid=54623
Автор: jazzer
Дата: 15.05.02
,
можно сделать вывод, что любые, внешние по отношению к классу, функции,
можно переделать в функции специального дочернего классса
(мои комплименты jazzer ).


Чесно говоря, мне трудно представить ситуацию, при котором подобная
функция должна иметь доступ не только к public, но и protected членам
базового класса.
Но даже в этом случае "Шаманство" нужно не очень сложное:
class foo 
{
protected:
    int ProtectedData;
private:
    int PrivateData;
public:
    int PublicData;

    inline foo(void)
        :    ProtectedData(1) ,PrivateData(2), PublicData(3)
    {};
    inline foo(const foo&ref)
        :    ProtectedData(ref.ProtectedData) ,
            PrivateData(ref.PrivateData), 
            PublicData(ref.PublicData)
    {};
    inline foo& operator=(const foo&ref)
    {
        ProtectedData=ref.ProtectedData;
        PrivateData=ref.PrivateData;
        PublicData=ref.PublicData;
        return *this;
    };
};

void IncProtected(foo& data)
{
    class AccessToProtected : public foo
    {
    public:
        inline void IncProtected(void)
        {
            ProtectedData++;
        };
    };
    reinterpret_cast<AccessToProtected&>(data).IncProtected(); 
};


или без шаманства, если базовый класс поддерживает оператор присваивания
void IncProtected2(foo& data)
{
    class AccessToProtected : public foo
    {
    public:
        inline AccessToProtected (const foo& ref)
            : foo(ref)
        {};

        inline void IncProtected(void)
        {
            ProtectedData++;
        };
    };
    AccessToProtected A(data);
    A.IncProtected();
    data=A;
};


Если же, требуемый дополнительный метод должен обращатьться к private
методам базового класса, то вероятно имеет место ошибка при проектировании.
Даже необходимость обращения к protected данным кажется подозрительной.
Re[2]: Расширение С++
От: WolfHound  
Дата: 24.03.03 18:07
Оценка:
Здравствуйте, WolfHound, Вы писали:

Опс бага вышла. Так правильно.
template <class Base>
class Empty:public Base{};
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Расширение С++
От: Denwer Россия  
Дата: 25.03.03 06:34
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


WH>Просто библиотеки нужно писать правильно.


Ага, ты мне предлагаешь написать в майкрософт и высказать свое недоверие тем, как они спроектировали MFC. Речь и идет как раз не о моих классах(в своей либе я могу делать что хочу), а о классах сторонних разработчиков, которые я править не могу(по разным причинам, например отсутствие исходников).
Re[6]: Расширение С++
От: Аноним  
Дата: 25.03.03 13:31
Оценка:
Впрочем, чтобы немного упростить себе жизнь, придумали аспектно-ориентированное программирование. В частности, задача с перемещениями фигур могла бы решаться при помощи такого аспекта (здесь приведен псевдокод):

. . .

Но это все уже выходит за пределы тематики C++.

--
Дмитрий
Re[8]: Ну это зря...
От: lboss Россия  
Дата: 28.03.03 08:44
Оценка:
Здравствуйте, Дмитро, Вы писали:


Д> ... Но я не помню, чтобы где-то я встречал что-то подобное.


Реально это не плохо используется в Object-C++, правда там можно рассширять классы только новыми методами (там они называются event'ами) — это приводит к довольно таки приятному деленюю классов на части относящиееся к разным областям применениям — например, рассширение строк для работы с именами файлов (не писать GetFileExt(string) а сделать спец рассширение к классу). Реально я считаю что данное рассширение С++ довольно приятноё — так как позволяет более правильно проектировать объектную модель и позволяет отделять непосредственно объект от утилит работы с ним...
С уважением Вадим.
Re[9]: Ну это зря...
От: Дмитро  
Дата: 28.03.03 10:15
Оценка:
Здравствуйте, lboss, Вы писали:

L>Реально это не плохо используется в Object-C++


Что это? Дай ссылку или другой какой источник.

--
Дмитрий
--
Дмитрий
Re[8]: Расширение С++
От: WolfHound  
Дата: 28.03.03 15:11
Оценка:
Здравствуйте, Дмитро, Вы писали:

Д>"модерновая иерархия" Андрея WolfHound.

Это у меня импровизации такие после того как Александреску начитался.
Д>Но я не помню, чтобы где-то я встречал что-то подобное, а если бы и встретил, то не сразу бы "догнал", что имеется в виду.
Прочитай Александреску будишь еще не такое понимать и придумывать.
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Расширение С++
От: limax Россия http://mem.ee
Дата: 09.05.03 14:40
Оценка:
Здравствуйте, IAZ, Вы писали:
IAZ>А то получается, что написал я графический редактор с использованием обычной библитеки классов (без извещения). А в один прекрасный момент программа стала посылать кому-то какие-то извещения!

"Значит это кому-нибудь нужно"
Have fun: Win+M, Ctrl+A, Enter
Re[9]: Расширение С++
От: limax Россия http://mem.ee
Дата: 09.05.03 14:54
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Прочитай Александреску будишь еще не такое понимать и придумывать.

Это?
http://oz.by/books/more104640.html
Взгляни на цену.
Have fun: Win+M, Ctrl+A, Enter
Re[7]: Расширение С++
От: MaximE Великобритания  
Дата: 09.05.03 19:21
Оценка:
Здравствуйте, IAZ, Вы писали:

IAZ>Здравствуйте, Аноним, Вы писали:


IAZ>>>Хороший способ расширения библиотеки классов — это использование оберток.


А>>Хороший! Тем не менее, он не всегда срабатывает. Например, если нужно добавить не просто методы, а и члены-данные.


IAZ>Почему? Кто запрещает поместить вместе с методом и атрибуты?


IAZ>

IAZ>
IAZ>template<class T>
IAZ>class X
IAZ>{
IAZ>public:
IAZ>   X(T* _a) : a(_a) {}
IAZ>   void h(); // метод
IAZ>   int k;    // атрибут
IAZ>   T* operator->()
IAZ>   {
IAZ>     return a;
IAZ>   }
IAZ>private:
IAZ>   T* a;
IAZ>};
IAZ>


Никто не запрещает, только какой в этом смысл. Как узнать, что такой атрибут изменился?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.