wlasny manipulator

0

Przypuscmy ze ma klase:

class cos {

    int x, y;

public:

    cos& operator<<(/*wlasnie tu nie wiem jaki argument*/);
}

I chcialbym osiagnac cos w tym stylu:
cos _c;
_c << setxy(1, 3);

funkcja setxy() mialaby zmieniac wartosci x i y w obiekcie _c. Pytanie jest proste: jak to zrobic ?

0

Nie rozumiem - dlaczego nie mozesz zastosowac zwyklej metody?

Zeby zrobic to w taki sposob jak napisales operator <<() musial by pobierac
wskaznik na metode/funkcje, ale nie sadze zeby to byl dobry i oplacalny pomysl.

0

po prostu chcialbym aby bylo to podobne do zapisu znanego ze standardowej biblioteki. np. cout << setw(9);

Wlasnie kombinowalem z tym wskaznikeim ale wszystkie moje proby konczyly sie bledami kompiatora...

0

Przejrzyj plik

iomanip.h

i będziesz wiedział jak to się robi ;)

0

np. tak:

#define KOMENDA_SETXY  0

typedef struct {
   int komenda;
   void* parametry;
} manipulator;

manipulator setxy(int x, int y)
{
   manipulator result;
   result.komenda = KOMENDA_SETXY;
   result.parametry = new int[2];
   ((int*) result.parametry)[0] = x;
   ((int*) result.parametry)[1] = y;
   return result;
}

class cos
{
private:
   int x, y;
public:
   cos& operator<<(manipulator M);
};

cos& cos::operator<<(manipulator M)
{
   switch(M.komenda)
   {
      case KOMENDA_SETXY:
      {
         x = ((int*) M.parametry)[0];
         y = ((int*) M.parametry)[1];
      }
   }
};
0

adf88: nie zabrakło gdzieś operatora

delete

??? ;)

0

no tak jeszce delete [wstyd]

...
      case KOMENDA_SETXY:
      {
         x = ((int*) M.parametry)[0];
         y = ((int*) M.parametry)[1];
         delete[2] ((int*) M.parametry);
      }
...

Zamiast struktury "manipulator" z parametrem "komenda" można stworzyć konkretne klasy z potrzebnymi polami dla konkretnych funkcji (np. funkcja "setxy" zwracałaby klase setxyclass { int x; int y; }, a zamiast funkcji operator<< ze switch'em na "komenda" stworzyć kilka przeciążonych funkcji operatora, które za parametr przyjmują konkretną klase manipulatora np cos& operator<<(setxyclass klasa) { x = klasa.x; y = klasa.y; return *this; }

0

hmm... pomyslowe :)

[dopisane]
Dziekuje oczywiscie :)

0

Dodam jeszcze, że użycie konkretnych struktur i przeciążonych operatorów zmniejszy i przyspieszy program.
Można też połaczyć (w miare potrzeb) opisane przeze mnie dwa sposoby i zrobić np. taką sztuczke:

#define SET_X        1
#define SET_Y        2 //nastepne opcje mialyby numery 4, 8 .. 
#define SET_XY       SET_X | SET_Y

typedef struct setxyclass {
   int flags;
   int x;
   int y;
   setxyclass(int _flags, int _x, int _y): flags(__flags), x(_x), y(_y) {};
} setxyclass;

setxyclass setxy(int x, int y, int flags = SET_XY)
{
   return setxyclass(flags, x, y);
}

#define setx(x) setxy(x, 0, SET_X)
#define sety(y) setxy(0, y, SET_Y)
0

Dzieki :)

Ja rozwiazalem to w ten sposob:



//------------------------------------------------------------------------------
// szablon dla jednoargumentowych manipulatorow
template <class TYPE>
class manip_one_arg {
public:
	manip_one_arg(TYPE _p) {
		parameter = new TYPE(_p);	
	}
	
	~manip_one_arg() {
		delete parameter;
	}
	
	TYPE*	parameter;
		
};

//------------
// szablon dla dwuargumentowych manipulatorow
template <class TYPE>
class manip_two_arg {
public:
	manip_two_arg(TYPE _p1, TYPE _p2) {
		parameter = new TYPE[2];
		
		parameter[0] = _p1;
		parameter[1] = _p2;	
	}
	
	~manip_two_arg() {
		delete[] parameter;
	}
	
	TYPE*	parameter;
		
};

//------------
// konstrukcja ramek
enum part {
	top_left,	top_right,
	h_line,		v_line,
	bot_left,	bot_right,
	cross,
	cross_left,	cross_right,
	top_cross,	bot_cross
};

//------------	
// tryby
enum mode {
	sing,
	doub
};

manip_two_arg<int> set_xy(int _x, int _y) {
	
	return manip_two_arg<int>(_x, _y);
}


class paintbox: public box {
protected:
	
	COLORS		color;
	char**		part_tab;
	mode		act_mode;
	unsigned	draw_posx, draw_posy;
	
public:
	
	paintbox(int, int, int, int, mode);
	~paintbox();
	
	
	inline paintbox& operator<<(part _p);
	
	paintbox& operator<<(mode _m){
		act_mode = _m;
	return *this;
	}
	
	paintbox& operator<<(manip_two_arg<int> manip) {
		if(manip.parameter[0] > 0 && manip.parameter[0] < width)
			x = manip.parameter[0];
		if(manip.parameter[1] > 0 && manip.parameter[1] < height)
			y = manip.parameter[1];
		
	return *this;	
	}
	
};


paintbox& paintbox::operator<<(part _p) {
	
	if(++draw_posx < width)
		scr[draw_posx][draw_posy] = part_tab[act_mode][_p];
	
	else if(++draw_posy < height)
		scr[draw_posx=x][draw_posy] = part_tab[act_mode][_p];
	
		
return *this;
}

Oczywiscie bazujac na twoim pomysle :d

0

A co jeśli jakaś inna funkcja będzie miała dwa int'y w argumentach ? Aby działało to poprawnie funkcja operator<< musi jakoś rozróżnić akcje do wykonania. W takim przypadku nie trzeba podawać informacji o tym która funckja ma być użyta. Zadba o to kompilator, gdy zdefiniujesz osobne klasy dla każdej funkcji. użycie wzorców wtedy jest nie potrzebne.

0

Przyznam, ze nie do konca rozumiem :-| Jesli inna funkcja bedzie miala dwa argumenty to nic nie szkodzi bo nie zwroci obiektu klasy mainp_one_arg lub manip_two_arg. A jesli zwroci to znaczy ze do tego zostala napisana... Wolalem uzyc wzorcow bo jestem z gory uprzedzony do makrodefinicji.

0

Chyba rozumiem w czym problem [wstyd]. A czy da sie to jakos rozwiazac bez makrodefinicji ?

0

W jakiś sposób musisz dać znać klasie co ma robić z podawanymi argumentami (funkcja operator<<), więc możliwości masz dwie:

  1. Użyć wzorców i umieścić dodatkowa zmienna w manip_xxx_arg, mówiąca jaką akcje wykonać.
  2. wg. mnie lepsze rozwiązanie (prosze o opinie ;) ) jest stworzyć konkretne klasy.

A makrodefinicji też nie trzeba używać, ale są one bardzo pomocne.

0

Troche namodzilem... :P

// ---flagi do manipulatorow----------
enum config_flags {
	set_x = 1,
	set_y = 2,
	newl = 4
};


//------------------------------------
class manip_newl {
public:
	manip_newl(config_flags _flag = newl) {
		flag = new config_flags(_flag);
	}
	
	~manip_newl() {
		delete config_flags;
	}
	
	config_flas*	flag;	
};


//-------------------------------------
class manip_xy {
public:
	manip_xy(int _x, int _y, config_flags _flag=(set_x | set_y) ) {
		x = new int(_x);
		y = new int(_y);
		flag = new config_flags(_flag);
	}
	
	~manip_two_arg() {
		delete x;
		delete y;
		delete flag;
	}
	
	int*			x, y;
	config_flags*	flag;	
};


//-------------------------------------
manip_xy set_x(int _x) {
	return manip_xy(_x, 0, set_x);
}


//-------------------------------------
manip_xy set_y(int _y) {
	return manip_xy(0, _y, set_x);
}


//-------------------------------------
manip_xy set_xy(int _x, int _y) {
	return manip_xy(_x, _y, set_x | set_y);
}

I do tego by byly dwa przeladowane operatory<< w klasie "cos". Co o tym myslicie ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1