LINUX.ORG.RU

C++: Выборочная передача аргументов


0

0

Подскажите решение:

Есть ф-ция a() из которой вызывается виртуальный метод f(.....).

void a() {
int a,b,c,d,e,f;
string s1, s2, s3;
...............

f(..., ..., ..., ...,..........);

}

Задача, в зависимости от наследованного класса передать f() определенные переменные ф-ции a() (a,b,c,d,e,f ...........). Класс выбирается из массива
по индексу.


в зависимости от наследованного класса

То-есть вызывать виртуальный метод вы собираетесь из базового класса, но при этом хотите подставить аргументы в зависимости от того кто отнаследован? Полиморфизм он ведь абстрагирует интерфейс от реализации, базовый класс по хорошему не должен знать кто от него отнаследован.

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

А лучше сделать в базовом доступ к передаваемым параметрам через ацесоры и вызывать один универсальный метод, в котором кто хочет - берут нужное:

class Base
{
protected:
  int dataA() const { return data_->a; }
  string dataS1() const { return data_->s1; }
  ...

  void a()
  {
    Data data;
    ...
    data_ = &data;
    f();
    data_ = 0;
  }

private:
  struct Data
  {
    int a,b,c,d,e,f;
    string s1, s2, s3;
  };
  const Data * data_;
};
Dendy ★★★★★
()
Ответ на: комментарий от x0r

Так я и так derived class знаю по номеру, просто надо разные аргументы соответствующему методу передавать.

drZlo
() автор топика
Ответ на: комментарий от Dendy

Несколько не так, есть абстрактный класс A с вирт методом f() = 0; от него наследуются A0, A1 ... An. Так вот, vector<A*> VA содержит соответствующие классы VA[0] - A0 и т.д. В каждом из них ессно переопределен f() и хочется еще чтоб аргументы в зависимости от класса разные принимал.

drZlo
() автор топика
Ответ на: комментарий от drZlo

суй аргументы в массив, и вопрос выбора значений решай внутри виртуальной функции.

или показывай весь код, и старательно объясняй, нахрена тебе это надо.

Love5an
()
Ответ на: комментарий от drZlo

Очевидно у вас неправильный подход к решению задачи. Если вы этого не осознаете, то смотрите в сторону RTTI.

anonymous
()
Ответ на: комментарий от Love5an

> суй аргументы в массив

Так в структуру же.

и старательно объясняй, нахрена тебе это надо.


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

И, учитывая твое, «старательно объясняй», ты объясни, что в проектировании не так ???

drZlo
() автор топика
Ответ на: комментарий от bk_

> use lisp, Luke

Ок, мне от дровины нужно получить данные, как можно быстрее их визуализировать и т.д. Lisp ? А в милиции разберутся, кто из нас luke )

drZlo
() автор топика
Ответ на: комментарий от RUSDACent

> Eslui ya pravilno ponyal, to kopat nugno v storonu va_list.

Понял в общем правильно, но это наследие С и поддерживается только для совместимости. Хотелось бы ++ решений )

drZlo
() автор топика
Ответ на: комментарий от drZlo
#include <cstdarg>
#include <cstdio>

#define va_start_assign(list, var)		((list) = ((char*)&var))
#define va_assign(lvalp, type, rval)	{ *((type*)lvalp) = rval; va_arg(lvalp, type); };

enum { fUSE_A = 1, fUSE_B = 2, fUSE_C = 4 };

struct Foo
{
virtual	~Foo( void ) {}

virtual void	f( va_list& args )
				{
					int a = va_arg( args, int );

					printf( "%d\n", a );
				}

virtual	size_t	usedArgs( void ) const		{ return fUSE_A; }
};

struct FooChild : public Foo
{
virtual void	f( va_list& args )
				{
					int b = va_arg( args, int );
					int c = va_arg( args, int );

					printf( "%d,%d\n", b, c );
				}

virtual	size_t	usedArgs( void ) const		{ return fUSE_B | fUSE_C; }
};

void CallF( Foo& obj, int a, int b, int c )
{
	va_list out;
	static char buf[ 512 ];
	va_start_assign( out, buf[ 0 ] );

	size_t args = obj.usedArgs();
	if( args & fUSE_A ) va_assign( out, int, a );
	if( args & fUSE_B ) va_assign( out, int, b );
	if( args & fUSE_C ) va_assign( out, int, c );

	va_end(out);
	va_start_assign( out, buf[ 0 ] );
	obj.f( out );
	va_end(out);
}

//-------------------------------------------------------------- 
int main(int argc,char** argv) 
{
	int a = 1, b = 2, c = 3;
	
	Foo obj;
	CallF( obj, a, b, c );

	FooChild objChild;
	CallF( objChild, a, b, c );
} 

решение практической ценности не имеет( т.к. сама задача - извращение ), но работает( проверял только на VC2010 )

lester ★★★★
()
Ответ на: комментарий от drZlo

>Да уж, изврат )

Что-то ФП'шников не видно ...

Думаешь ФП'шники посоветуют нечто отличное от «неиспользовать плюсы»?

SV0L0CH
()
Ответ на: комментарий от drZlo

> Да уж, изврат )

а как еще? я пока вижу только три варианта

1. использовать switch( в том или ином виде ), тогда виртуальная функция с переменным кол-вом параметров не нужна
2. передавать все
3. забивать все в стек и вытаскивать, данные что нужно забивать получаем либо от объекта через виртуальный метод, либо маппим на его тип, который получаем через typeid, организация стека может быть разной - по сути va_list тут и не нужен

lester ★★★★
()
Ответ на: комментарий от drZlo

и кстати, что мешает создать структуру, в нее складывать значения, а потом просто передать указатель?

lester ★★★★
()
Ответ на: комментарий от lester

> 1.

Вот от этого и хочу избавиться.

2.


Так и делаю сейчас.

3.


Ну эт слишком.

а как еще?


Ну вот думал может вдруг... )

drZlo
() автор топика
Ответ на: комментарий от lester

Так ща и делаю. Но надо передавать всегда все возможные данные, что, кривова-то, но т.к. остальное еще костыльнее, то ...

drZlo
() автор топика
Ответ на: комментарий от drZlo

> Несколько не так, есть абстрактный класс A с вирт методом f() = 0; от него наследуются A0, A1 ... An. Так вот, vector<A*> VA содержит соответствующие классы VA[0] - A0 и т.д. В каждом из них ессно переопределен f() и хочется еще чтоб аргументы в зависимости от класса разные принимал.

и?

и в чем проблема *именно так* и сделать?

пиши код, который можно скормить ж++ и увидеть его реакцию.

www_linux_org_ru ★★★★★
()

Хм, такое ощущение, что все отвечают только на первый пост (вопрос), а все промежуточные никто не читает )

drZlo
() автор топика
Ответ на: комментарий от drZlo

> Но надо передавать всегда все возможные данные, что, кривова-то

передается только указатель( ссылка ) - т.е. 4/8 байт( для x86 ), а то что в «пределы прямой видимости» попадают лишние данные - это вполне нормально, никто не заставляет использовать всегда все поля структуры :)

lester ★★★★
()
Ответ на: комментарий от Booster

> А что в этих переменных

Это не моя тайна )))

drZlo
() автор топика
Ответ на: комментарий от drZlo

> Товарищ, причем здесь RTTI ?

Вам уже говорили про вариант с использованием typeid, а он к вашему сведению без RTTI не работает.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.