Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.12.2012, 16:25   #1
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию Задать указатель на контейнер

Всех с наступающим.....
Вот как щас задам вопрос....

Есть иерархия, пляшущая от одного базового класса, условно такого:
Код:
class base
{
	base * pcontainer;
	
	base * setcontainer()
	{
		return NULL; // временно так
	}
public:
	base() : pcontainer( setcontainer() )
	{

	}
	virtual size_t mysize()	{ return sizeof(base);	}
};

Наследники выглядят приблизительно так:
Код:
class somecls : public base
{
	base agregate1;
	base agregate2;
	//... итд
public:
	size_t mysize() 	{ return sizeof(somecls); }
};

class anothercls : public somecls
{ 
	base agregate11;
	somecls agregate12;
	//... итд
public:
	size_t mysize() 	{ return sizeof(anothercls); }
};
Задача такая,
задать произвольному числу агрегатов указатель на контейнер. Как решить общий случай?

все решение должно быть только здесь:
base * setcontainer()
{
return NULL; // временно так
}

Интуитивно вижу, что решить можно, но пока не догоняю.
EUGY вне форума Ответить с цитированием
Старый 25.12.2012, 16:34   #2
Rififi
Старожил
 
Регистрация: 19.08.2009
Сообщений: 2,119
По умолчанию

EUGY

задать произвольному числу агрегатов указатель на контейнер. Как решить общий случай?

Этот указатель у них и так уже есть, неявно, и никаких setcontainer не нужно.
внутри, класса-агрегата, например конструктора:

Код:
somecls* p =
	reinterpret_cast<somecls*>(
		reinterpret_cast<char*>(this) - offsetof(somecls, agregate1)
		);
Rififi вне форума Ответить с цитированием
Старый 25.12.2012, 16:47   #3
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Не въехал..
Откуда классу, который может являться полем произвольного контейнера знать, к чему кастоваться и какой у него офсет по отношению к контейнеру?
В конструкторе контейнера я конечно могу явно указать всем членам нужные данные.
Вопрос, как не трогать конструкторы производных, а решить все в базовом.
EUGY вне форума Ответить с цитированием
Старый 25.12.2012, 20:19   #4
Perchik71
С++, Delphi
Форумчанин
 
Аватар для Perchik71
 
Регистрация: 24.11.2012
Сообщений: 495
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Не въехал..
Откуда классу, который может являться полем произвольного контейнера знать, к чему кастоваться и какой у него офсет по отношению к контейнеру?
В конструкторе контейнера я конечно могу явно указать всем членам нужные данные.
Вопрос, как не трогать конструкторы производных, а решить все в базовом.
простая штука.... как я понял... из примера выше.. происходит смена типа. почему можно... любой класс наследник может преобразоваться в класс из своей иерархии.... связи с тем, что наследник и базовый класс, память у них общая.
//-------------
Например в делфяке в самом базовом классе есть метод.. поиска других методов
Код:
GetAddressMethod(Func: String): Pointer;
её можно вызывать даже в вонючем и самом отдалёном классе внука.. допустим TImage.
при этом этой функции не мешает искать адрес методов всех дедов и бабушек.
Если помог, тут весы есть , Вам не сложно, а мне приятно.

Последний раз редактировалось Perchik71; 25.12.2012 в 20:33.
Perchik71 вне форума Ответить с цитированием
Старый 25.12.2012, 20:44   #5
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Может я не правильно объяснил.
Совсем с элементарного начну..
Вот структура:
Код:
struct S
{
	int y;
        int x;
};


int main()
{
	
	S s;
	int x = 1;
	s.x = 2;
        void * p1 = &x;
        void * p2 = &S.x;
}
переменная x объявленная в структуре и отдельно от нее это ведь разные разные экземпляры одного типа. Как зная только указатель, выяснить принадлежит ли это какому-то контейнеру или отдельно.
Структура знает свои поля, но как поле должно определить свой контейнер, если он вообще есть.
Продолжая аналогию, тот же вопрос можно задать о классах.
Класс это та же структура. Используя только конструктор базового класса, как выяснить принадлежность поля.

Я навскидку накидал решение в лоб, но что-то не нравится.
Код:
base * setcontainer()
	{
		static std::vector<base*> array;
		base * testcontainer = array.size() ?  array.back() : NULL;
		if ( NULL == testcontainer || this <= testcontainer)
		{
			testcontainer = NULL;
			array.clear();
		}
		else if (testcontainer)
		{
			char* maxadr = (char*)testcontainer + testcontainer->mysize() - mysize();
			if ((char*) this >  maxadr)
			{
				array.pop_back();
				if (array.size())
					return setcontainer();
			}
		}
		array.push_back(this);
		return testcontainer;
	}

Последний раз редактировалось EUGY; 25.12.2012 в 20:49.
EUGY вне форума Ответить с цитированием
Старый 25.12.2012, 21:09   #6
Perchik71
С++, Delphi
Форумчанин
 
Аватар для Perchik71
 
Регистрация: 24.11.2012
Сообщений: 495
По умолчанию

Код:
static std::vector<base*> array;
		base * testcontainer = array.size() ?  array.back() : NULL;
здесь всегда NULL
хотя нее
должен сработать array.back()
и только array.back().
но поскольку массив пустой бэкать там собственно нечего.
/------------------
Цитата:
Как зная только указатель, выяснить принадлежит ли это какому-то контейнеру или отдельно.
можно попробовать в структуре огранизовать empty().
Код:
size_t start = this;
size_t end = start + sizeof(*this);
return ((start <= p)&&(p<=end));
типо ссылка в районе памяти. но лучше использовать memcmp
Если помог, тут весы есть , Вам не сложно, а мне приятно.

Последний раз редактировалось Perchik71; 25.12.2012 в 21:20.
Perchik71 вне форума Ответить с цитированием
Старый 25.12.2012, 22:01   #7
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Я такой принцип проверки и написал, если this попадает в диапазон предыдущего
prevthis + sizeof(*prevthis) то поле принадлежит контейнеру. А так как классы имеют древовидную структуру, то нужно где-то хранить пройденные узлы. Вот функция их рекурсивно просматривает. Код-то работает, меня сам принцип смущает.
EUGY вне форума Ответить с цитированием
Старый 26.12.2012, 09:34   #8
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,368
По умолчанию

Цитата:
Сообщение от Perchik71 Посмотреть сообщение
Код:
static std::vector<base*> array;
		base * testcontainer = array.size() ?  array.back() : NULL;
здесь всегда NULL
хотя нее
должен сработать array.back()
и только array.back().
но поскольку массив пустой бэкать там собственно нечего.
Массив пустой только в первый вызов, потом в нем уже будут данные.
waleri вне форума Ответить с цитированием
Старый 26.12.2012, 09:35   #9
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,368
По умолчанию

Я не понимаю, что мешает передавать указатель на контейнер явно, при создании вложенного объекта?
waleri вне форума Ответить с цитированием
Старый 26.12.2012, 12:05   #10
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Цитата:
Я не понимаю, что мешает передавать указатель на контейнер явно, при создании вложенного объекта?
Мешает количество вложенных объектов и варианты перегруженных конструкторов контейнеров. Монструозно выходит.
Код:
class CONTEINER1: public base
{
	base a1;
	base a2;
	base a3;

	base b1;
	base b2;
	base b3;
	
	CONTEINER1(base* pprevcont) :
	a1(this), a2(this),... 
	{
		pconteiner = pprevcont;
	}

	CONTEINER1(): a1(this), a2(this),...
	CONTEINER1(int): a1(this), a2(this),...

};
И такой кошмар для всех наследников.
Вот я и хочу, используя только один конструктор базового класса задать всем вложенным объектам нужный указатель на корневой объект.
Еще была мысль в базовом классе проинициализировать диапазон адресов this + sizeof(*this) нужными данными, подобно тому, как в дебажных версиях память заполняется всякими там 0xCCCCCCCC.
Но как быть с проверкой валидности указателя.
EUGY вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Передать указатель на указатель в функцию erro Общие вопросы C/C++ 3 29.10.2012 17:59
VBA удалить столбцы, задать фикс. ширину столбца и задать перенос по словам johny_03 Microsoft Office Excel 1 14.04.2011 20:53
Контейнер ! curtcobain Общие вопросы Delphi 3 04.02.2009 20:27
ассоциативный контейнер SERGOO Общие вопросы C/C++ 4 17.06.2007 11:05