Может ли объект "узнать" где он создается?
От: niralex  
Дата: 21.02.12 17:01
Оценка:
Можно ли в конструкторе объекта без параметров каким-либо образом получить указатель на объект в котором он создается (в случае композиции):

class B;
class A
{
   public:
      A()
      {
          /* здесь нужно получать указатель на родительский объект или NULL, если объект создается глобально*/
      }
};
class B
{
   public:
      A a1;
};


Буду очень благодарен за любые решения, идеи или ссылки на материалы, где можно почитать по теме.
Re: Может ли объект "узнать" где он создается?
От: Vamp Россия  
Дата: 21.02.12 17:28
Оценка: 2 (1) +1
N>Можно ли в конструкторе объекта без параметров каким-либо образом получить указатель на объект в котором он создается (в случае композиции):
Полагаю, что никак. Более того, к моменту вызова конструктора внутреннего класса внешний еще не создан — и смысла в этом указателе в практическом плане я не вижу.
Да здравствует мыло душистое и веревка пушистая.
Re: Может ли объект "узнать" где он создается?
От: Константин Россия  
Дата: 21.02.12 17:52
Оценка:
Здравствуйте, niralex, Вы писали:


N>Можно ли в конструкторе объекта без параметров каким-либо образом получить указатель на объект в котором он создается (в случае композиции):

N>Буду очень благодарен за любые решения, идеи или ссылки на материалы, где можно почитать по теме.

Интересно, а что за задача решается?
Re: Может ли объект "узнать" где он создается?
От: MasterZiv СССР  
Дата: 21.02.12 18:31
Оценка: 2 (1)
> Можно ли в конструкторе объекта без параметров каким-либо образом
> получить указатель на объект в котором он создается (в случае композиции):

Нельзя.

> Буду очень благодарен за любые решения, идеи или ссылки на материалы, где можно

> почитать по теме.

Решение простое -- сделай соотв. конструктор, вызывай его в "родителе",
передавай "ребёнку" ссылку на "родителя".
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Может ли объект "узнать" где он создается?
От: niralex  
Дата: 21.02.12 19:10
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Нельзя.


MZ>Решение простое -- сделай соотв. конструктор, вызывай его в "родителе",

MZ>передавай "ребёнку" ссылку на "родителя".

это решение понятно, но я искал решение без передачи параметра в конструктор.
Re[3]: Может ли объект "узнать" где он создается?
От: MasterZiv СССР  
Дата: 21.02.12 19:58
Оценка:
> MZ>Решение простое -- сделай соотв. конструктор, вызывай его в "родителе",
> MZ>передавай "ребёнку" ссылку на "родителя".
>
> это решение понятно, но я искал решение без передачи параметра в конструктор.

Тебе же сказали, в рамках языка С++ нет. можешь искать дальше, конечно, дело твоё.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Может ли объект "узнать" где он создается?
От: niralex  
Дата: 21.02.12 21:31
Оценка:
Спасибо всем за ответы.

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

К>Интересно, а что за задача решается?



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

В одном из решений задачи, которое используется в данный момент, все классы рассмотриваются как контейнеры специальных объектов-свойств, которые в общем случае являются простыми оболочками для стандартных типов.
Это выглядит примерно так:

class Property // базовый класс свойств
{
    public:
        string Name;   // имя свойства
        // ...
        Property(string AName) : Name(AName) {}
};
class IntProperty : public  Property // свойство-оболочка для типа int
{
    private:
        int _value;
    public:
        IntProperty(string AName, int AValue) : Property(AName), _value(AValue) {}
        int &Value() { return _value; } // доступ к значению свойства
};

class BaseComponent // базовый класс иерархии компонентов
{
    protected:
        std::vector<Property*>  _props; // свойства компонента
    public:
        // обобщенный интерфейс, наследуемый потомками
                int CountProperties()const { return _props.size(); }
        Property *GetProperty(int AIndex) { return _props[AIndex]; }
};
// пример класса иерархии
class ComponentExample : public BaseComponent
{
    private:
       // специфические данные компонента
       IntProperty _data; // вместо int _data;

    public:
       ComponentExample() : _data("NameProperty", 0)
       {
           _props.push_back(&_data); // 1
       }
       // специализированный интерфейс компонента
           // ...


Проблема здесь в том, что в конструкторах производных классов необходимо добавлять свойства вручную(строка 1) и если кто-то для чего-то забыл это сделать, то получаем баги, связанные с тем, что реально переменная в компоненте есть, а в обощенном интерфейсе ее нет.

Возникла идея, чтобы конструкторы классов свойств сами себя добавляли в контейнер _props. Благо, иерархия классов свойств относительно небольшая и устоявшаяся. Для этого и понадобилось узнать где объект-свойство создается. Имея указатель на родительский объект, свойство смогло бы само себя добавить в конструкторе. Но, пока не знаю как это реализовать. Возможно, кто-нибудь подскажет другие идеи?
Re[3]: Может ли объект "узнать" где он создается?
От: night beast СССР  
Дата: 22.02.12 03:58
Оценка:
Здравствуйте, niralex, Вы писали:

N>Возникла идея, чтобы конструкторы классов свойств сами себя добавляли в контейнер _props. Благо, иерархия классов свойств относительно небольшая и устоявшаяся. Для этого и понадобилось узнать где объект-свойство создается. Имея указатель на родительский объект, свойство смогло бы само себя добавить в конструкторе. Но, пока не знаю как это реализовать. Возможно, кто-нибудь подскажет другие идеи?


здесь
Автор: enji
Дата: 20.02.12
Re[4]: Может ли объект "узнать" где он создается?
От: niralex  
Дата: 22.02.12 06:34
Оценка:
Здравствуйте, night beast, Вы писали:

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


N>>Возникла идея, чтобы конструкторы классов свойств сами себя добавляли в контейнер _props. Благо, иерархия классов свойств относительно небольшая и устоявшаяся. Для этого и понадобилось узнать где объект-свойство создается. Имея указатель на родительский объект, свойство смогло бы само себя добавить в конструкторе. Но, пока не знаю как это реализовать. Возможно, кто-нибудь подскажет другие идеи?


NB>здесь
Автор: enji
Дата: 20.02.12

Спасибо, идея хорошая, но немного не то что надо. В контексте моей задачи концепция свойств другая(возможно, просто я неудачное название выбрал). В данном случае свойства не обязательно должны маскироваться под переменную, а просто обеспечивать доступ к переменным обобщенным способом.
Re[3]: Может ли объект "узнать" где он создается?
От: Erop Россия  
Дата: 22.02.12 08:22
Оценка: 3 (1)
Здравствуйте, niralex, Вы писали:

N>Требуется разработать базовый класс иерархии, который бы обеспечивал обобщенный унифицированный интерфейс доступа ко всем объектам иерархии. При этом количество классов велико, классы разрабатываются разными людьми для разных задач. Под доступом понимается возможность обращаться к членам классов для чтения/изменения значений. Другими словами, каждый класс должен иметь два интерфейса, один из котороых обощенный, чтобы со всеми объектами можно было работать однотипно.


N>В одном из решений задачи, которое используется в данный момент, все классы рассмотриваются как контейнеры специальных объектов-свойств, которые в общем случае являются простыми оболочками для стандартных типов.


А нужно иметь возможность создавать одинокие свойства? Которые не лежат в контейнере?
А то можно же просто добавить в конструктор свойства BaseComponent*, и всё сразу заиграет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Может ли объект "узнать" где он создается?
От: night beast СССР  
Дата: 22.02.12 08:55
Оценка: 2 (1)
Здравствуйте, niralex, Вы писали:

N>>>Возникла идея, чтобы конструкторы классов свойств сами себя добавляли в контейнер _props. Благо, иерархия классов свойств относительно небольшая и устоявшаяся. Для этого и понадобилось узнать где объект-свойство создается. Имея указатель на родительский объект, свойство смогло бы само себя добавить в конструкторе. Но, пока не знаю как это реализовать. Возможно, кто-нибудь подскажет другие идеи?


NB>>здесь
Автор: enji
Дата: 20.02.12

N>Спасибо, идея хорошая, но немного не то что надо. В контексте моей задачи концепция свойств другая(возможно, просто я неудачное название выбрал). В данном случае свойства не обязательно должны маскироваться под переменную, а просто обеспечивать доступ к переменным обобщенным способом.

то есть, как реализована там передача информации о родителе ты посмотрел?
Re: Может ли объект "узнать" где он создается?
От: gegMOPO4  
Дата: 22.02.12 09:46
Оценка: 2 (1) -1
21.02.12 19:01, niralex написав(ла):
> Можно ли в конструкторе объекта без параметров каким-либо образом получить указатель на объект в котором он создается (в случае композиции):

[perversion mode on]
Контейнер наследуется от базового класса, который сохраняет ссылку на
себя в глобальной переменной. Компонента проверяет эту ссылку в
конструкторе и сбрасывает её.

Разумеется, есть множество случаев, когда это «работать» не будет.
[perversion mode off]
Posted via RSDN NNTP Server 2.1 beta
Re: Может ли объект "узнать" где он создается?
От: denisko http://sdeniskos.blogspot.com/
Дата: 22.02.12 10:43
Оценка: :)
Здравствуйте, niralex, Вы писали:


N>Буду очень благодарен за любые решения, идеи или ссылки на материалы, где можно почитать по теме. C чем связано требование про без параметров? Если требование не строгое, а нужно, чтобы объект просто вел себя как будто у него есть конструктор без параметров, то можно передавать туда значения по умолчанию. Типа такого


//какая фигня описывающая контекст
struct Context
{
   int a;
};

//получение контекста, вся логика обработки именно в этой функции
Context* getGlobalContext()
{
   return NULL;
}
//многострадальная пропертя
struct PropertyType
{
   PropertyType(Context* c = getGlobalContext())
   {
    ;
   }
   ~PropertyType()
   {
      ;
   }
   int b;
};
<Подпись удалена модератором>
Re[2]: Может ли объект "узнать" где он создается?
От: denisko http://sdeniskos.blogspot.com/
Дата: 22.02.12 12:42
Оценка:
Здравствуйте, denisko, Вы писали:

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



N>>Буду очень благодарен за любые решения, идеи или ссылки на материалы, где можно почитать по теме. C чем связано требование про без параметров? Если требование не строгое, а нужно, чтобы объект просто вел себя как будто у него есть конструктор без параметров, то можно передавать туда значения по умолчанию. Типа такого

Кстати подумал, есть еще грязный способ через переопределение unexpected (тогда и никаких параметров не надо передавать вообще), но он, работает только в теории, и слава богу.
<Подпись удалена модератором>
Re[4]: Может ли объект "узнать" где он создается?
От: niralex  
Дата: 22.02.12 17:03
Оценка:
Здравствуйте, Erop, Вы писали:

E>А нужно иметь возможность создавать одинокие свойства? Которые не лежат в контейнере?

E>А то можно же просто добавить в конструктор свойства BaseComponent*, и всё сразу заиграет...

Одинокие свойства не нужны. Считается, что они неотделимы от компонента.
Если я правильно понял мысль, то конструкторы свойств должны быть такими:
SomeProperty::SomeProperty(BaseComponent* Parent){}

а компонент будет обязан передавать this при создании свойства.
Такой вариант рассматривается, он всем хорош, но пугает небольшая проблема — вдруг кто-то передаст вместо this, указатель на какой-нибудь другой компонент...
Re[6]: Может ли объект "узнать" где он создается?
От: niralex  
Дата: 22.02.12 17:08
Оценка:
Здравствуйте, night beast, Вы писали:

NB>>>здесь
Автор: enji
Дата: 20.02.12

N>>Спасибо, идея хорошая, но немного не то что надо. В контексте моей задачи концепция свойств другая(возможно, просто я неудачное название выбрал). В данном случае свойства не обязательно должны маскироваться под переменную, а просто обеспечивать доступ к переменным обобщенным способом.

NB>то есть, как реализована там передача информации о родителе ты посмотрел?


нет, глубоко не вник, при поверхностном рассмотрении показалось что не то, извиняюсь.
Сейчас пытаюсь разобраться, но сложновато для моего уровня...
Re[2]: Может ли объект "узнать" где он создается?
От: niralex  
Дата: 22.02.12 17:28
Оценка:
Здравствуйте, gegMOPO4, Вы писали:

MOP>[perversion mode on]

MOP>Контейнер наследуется от базового класса, который сохраняет ссылку на
MOP>себя в глобальной переменной. Компонента проверяет эту ссылку в
MOP>конструкторе и сбрасывает её.

MOP>Разумеется, есть множество случаев, когда это «работать» не будет.

MOP>[perversion mode off]

Согласен, это решает и тоже рассматривается как вариант. Я даже писал рабочий набросок кода который все это реализует, правда немного усовершенствованный — для создания компонента используется глобальная функция, которая сбрасывает глобальный указатель, чтобы это не "забывали" делать компоннеты. Но в этом варианте не нравится использование глобальной переменной. Например, как быть, если в компоненте создается вложенный компонент(хотя это можно попробовать решить через стек глобальных указателей на компоненты, которые создаются в данный момент) или что будет в многопоточном приложении, где каждый объект содает свои компоненты? В целом, чувствую, что как-то это все не так...
Re[7]: Может ли объект "узнать" где он создается?
От: night beast СССР  
Дата: 22.02.12 19:03
Оценка:
Здравствуйте, niralex, Вы писали:

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


NB>>>>здесь
Автор: enji
Дата: 20.02.12

N>>>Спасибо, идея хорошая, но немного не то что надо. В контексте моей задачи концепция свойств другая(возможно, просто я неудачное название выбрал). В данном случае свойства не обязательно должны маскироваться под переменную, а просто обеспечивать доступ к переменным обобщенным способом.

NB>>то есть, как реализована там передача информации о родителе ты посмотрел?


N>нет, глубоко не вник, при поверхностном рассмотрении показалось что не то, извиняюсь.

N>Сейчас пытаюсь разобраться, но сложновато для моего уровня...

если в двух словах, то для каждого свойства генерируется свой класс вида:
struct Container 
{
  struct Property_UNIQUEID
  {
    Container * parent ( ) { 
      return reinterpret_cast<Container *>( reinterpret_cast<char *>(this) - offsetof(Container,value) );
    }
  } value;   
};

int main ( )
{
   Container x;
   std::cout << &x << "==" << x.value.parent( ) << std::endl;
}
Re[3]: Может ли объект "узнать" где он создается?
От: niralex  
Дата: 22.02.12 20:39
Оценка:
Всем спасибо за помощь! Полезной информации получил много, буду переваривать.
Re[5]: Может ли объект "узнать" где он создается?
От: Erop Россия  
Дата: 22.02.12 21:58
Оценка: 3 (1)
Здравствуйте, niralex, Вы писали:

N>Такой вариант рассматривается, он всем хорош, но пугает небольшая проблема — вдруг кто-то передаст вместо this, указатель на какой-нибудь другой компонент...


Ну у него и не взлетит...

Но тут можно зайти ещё и с другой стороны.
#include <map>
#include <string>

struct INamedProperty {
    const std::string Name;

    INamedProperty( const std::string& name_ ) : Name( name_ ) {}
    virtual ~INamedProperty() {}
};

template<typename T>
class CNamedProperty : public INamedProperty {
    T data;
public:
    CNamedProperty( const std::string name_ ) : INamedProperty( name_ ), data( T() ) {}
    
    T& Get() { return data; }
    template<typename Y> operator Y() { return data; }
};

class CPropertiesSet {
public:
    INamedProperty* GetIProperty( const std::string& name ) 
    {
        propertiesStorage_t::iterator p = properties.find( name );
        return p != properties.end() ? p->second : 0;
    }
    
    template<typename T>
    CNamedProperty<T>* GetProperty( const std::string& name ) 
        { return dynamic_cast<CNamedProperty<T>*>( GetIProperty( name ) ); }

    template<typename T>
    T& GetPropertyData( const std::string& name ) 
        { return GetProperty<T>( name )->Get(); }

protected:
    CPropertiesSet() {}
    virtual ~CPropertiesSet() 
    {
        for( propertiesStorage_t::iterator p = properties.begin(); p != properties.end(); ++p ) {
            setPropertyPtr( p->second, 0 ); 
        }
    }

    template<typename T> T& addProperty( const std::string& name )
    {
        CNamedProperty<T>* p = new CNamedProperty<T>( name );
        properties[name] = p;
        return p->Get();
    }
private:
    typedef std::map<std::string, INamedProperty* > propertiesStorage_t;
    propertiesStorage_t properties;

    CPropertiesSet( const CPropertiesSet& );
    void operator = ( const CPropertiesSet& );
    static void setPropertyPtr( INamedProperty*& dst, INamedProperty* toSet )
    {
        if( dst != toSet ) {
            std::swap( dst, toSet );
            delete toSet;
        }
    }


};
///////////////////////////

struct TestClass : CPropertiesSet {
    int& X;
    std::string& Y;

    TestClass() : 
        X( addProperty<int>( "X" ) ), 
        Y( addProperty<std::string>( "Y" ) )
    {
    }

    static int testIt()
    {
        TestClass x;
        x.GetPropertyData<int>( "X" ) = 5;
        return x.X;
    }
};
типа свойства вообще всегда хрянятся внутри базы, а в нследниках если надо, запонимают ссылки на нужные переменные.
Кстати, при таком подходе, я бы ещё и имена у пропертей поубирал, зачем они им? По идее, имя должно знасть множество.

А у вас множественное наследование бывает?

На самом деле в этой всей системе есть один косяк. Свойства, по идее, можно бы регить на тип, а не на экземпляр...
Так и быстрее и веселее должно быть.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.