Adott egy egyszerű exception osztály, ami változó hosszúságú argumentumlistát fogad! Úgy szeretném megcsinálni, hogy a user csak a konstruktoron keresztül adhassa ezt át, míg a gyerekosztályok kapnak egy protected setMessage() függvényt. Logikus lenne, ha a konstruktor a setMessage() függvényt hívná, de valamiért ilyenkor lenyelődik, azaz inkább felülíródik az első paraméter értéke.
Mivel a 'C'-s vsnprintf függvény hívása problámamentes, ezért gondolom azzal lehet összefüggésben a dolog, hogy a setMessage 'C++' függvény.
Nos ismeri valaki a 'C++'-os függvények hívási specifikációját, vagy megadhatom e egy osztály memberfüggvényére, hogy extern "C", vagy egyéb
ötlete illetve magyarázata van valakinek? :)Ez a kód:
#include <iostream>
#include <cstdio>
#include <cstdarg>
using namespace std;
#define BUFF_SIZE 1024
class Exception {
public:
Exception(const char *format, ...) {
va_list args;
va_start (args, format);
setMessage(format, args);
va_end (args);
}
const char* getMessage() const {
return message.c_str();
}
//protected:
void setMessage(const char *format, ...) {
char buffer[BUFF_SIZE];
va_list args;
va_start (args, format);
vsnprintf (buffer,BUFF_SIZE, format, args);
va_end (args);
message = std::string(buffer);
}
private:
std::string message;
};
int main(void)
{
try {
throw Exception("1:%s,2:%s,3:%s","1","2","3");
} catch(Exception e) {
cerr << "Exception: " << e.getMessage() << endl;
}
try {
Exception e("");e.setMessage("1:%s,2:%s,3:%s","1","2","3"); throw e;
}
catch(Exception e) {
cerr << "Exception: " << e.getMessage() << endl;
}
}
Ez a kimenet:
Exception: 1:,2:2,3:3
Exception: 1:1,2:2,3:3
- 1463 megtekintés
Hozzászólások
Szerintem a ... paraméterű függvények nem tudnak va_list típusú változót fogadni. Gondolom, ezért van külön printf és vprintf függvény.
Lehet, hogy a va_copy lesz jó Neked - nézd át, én még nem használtam.
Amúgy nekem semmi gondom nem volt C++-ban az stdarg-gal.
- A hozzászóláshoz be kell jelentkezni
+1
/* protected: */ void setMessage(const char *format, ...)
helyett
void setMessage(const char *format, va_list args)
. Egy fv vagy (...)-os vagy va_list-es (akkor a va_list akarhanyadik artumentum lehet, es lehet belole tobb is, elvegre az csak egy pointer), de keverni nem lehet...
- A hozzászóláshoz be kell jelentkezni
Ahha! Asszem értem! Ezekszerint a va_list-es marhaság kb. annyi, hogy ad néhány makrót arra, hogy elővakarja a paramétereket (mondjuk a veremből). Maga a va_list egy pointer (void *) amit a va_start-tal állít be, a va_arg-gal léptet + visszaadja a mutatott értéket, a va_end-del meg megszűntet. De amikor a va_list-tel továbbhívok, akkor már egy olyan függvényem van, aminek a második paramétere a void* pointer, ami az előző hívás stackjében mutat valahova. De mivel megint ráhívtam egy va_startot, úgy kezelem mintha n paramétere lenne, tehát az első paraméter helyére kiírta a va_list pointer értékét, a másik kettő meg még ott volt a stackben mögötte/előtte, ezért merő véletlen volt, hogy megjelent.
- A hozzászóláshoz be kell jelentkezni
Jaja. Ha 1/ tutibiztos hogy nincs inline optimalizacio 2/ a parameterek egy stack szeru" dolgon kerulnek atadasra (i386 arch-on forditott sorrendben vermelve), akkor a va_* makrok igy helyettesitheto"ek:
typedef char * va_list;
#define va_start(list,last) do { list=(char *)(&last)+sizeof(last) } while(0)
#define va_arg(list,type) (list+=sizeof(type),*((type *)(list-sizeof(type)))
#define va_end(list) ((void)0)
csak ugye ezt nem hasznalhatod direkte mert a fordito nem a stack-ra pakolja a parametereket... legalabbis nem biztos.
- A hozzászóláshoz be kell jelentkezni
Erre nem is gondoltam. A vprintf paraméterezéséből tippeltem, hogy így lehet továbbhívni tetszőleges '...' paraméteres függvényre. Mindenesetre 'pure' C-ben sem működik, szóval nem C++ specifikus a dolog, hanem nem így kell továbbhívni! Megyek kiderítem, hogy hogyan ... :)
#include <stdio.h>
#include <stdarg.h>
void fn2(char *format, ...)
{
va_list args;
va_start (args, format);
vprintf(format, args);
va_end (args);
}
void fn1(char *format, ...)
{
va_list args;
va_start (args, format);
fn2(format, args);
va_end (args);
}
int main(void)
{
fn2("1:%s 2:%s 3:%s\n", "1","2","3");
fn1("1:%s 2:%s 3:%s\n", "1","2","3");
return 0;
}
1:1 2:2 3:3
1 2: 3:3
- A hozzászóláshoz be kell jelentkezni
használj
[code]
tageket, mert könnyen elvesznek részletek a kódból. Most csak az include hiányzik, de ha templatek is lennének...
- A hozzászóláshoz be kell jelentkezni
Használtam! De nekem sem jelenik meg az include ...
Teszt:
#include "cica"
#include <cica>
#include <cica.h>
[ code ]
#include "cica"
#include <cica>
#include <cica.h>
[ /code ]
- A hozzászóláshoz be kell jelentkezni
A paraméterelcsúszásról jut eszembe, tök más dolog, de mégis jól jöhet itt, ezen a szálon: nézd meg a következő gcc-kiterjesztést is:
függvény (const char *form, ...) __attribute__ ((format (printf, 1, 2)));
figelmeztet a fordító, ha nem a formátumnak megfelelő paramétereket adtad. Kis gond: C++-ban elcsúszik a számozás; gondolom, a láthatatlan this paraméter miatt:
class valami
{
metódus (const char *form, ...) __attribute__ ((format (printf, 2, 3)));
}
- A hozzászóláshoz be kell jelentkezni
Hasznos infó! Szerintem is a this a ludas itt. Én is a this-re gondoltam, amikor paraméterelcsúszást írtam, de azóta sikerült megfejteni a jelenséget.
- A hozzászóláshoz be kell jelentkezni
void setMessage(const char *format, va_list args) {
char buffer[BUFF_SIZE];
vsnprintf (buffer,BUFF_SIZE, format, args);
message = std::string(buffer);
}
- A hozzászóláshoz be kell jelentkezni
igen, ez lett végül, csak így meg kell még egy void setMessage(const char *format, ...) nevű overload is
- A hozzászóláshoz be kell jelentkezni
Ajánlom figyelmedbe a boost::format-ot: szép, típusbiztos, mi kell még?
- A hozzászóláshoz be kell jelentkezni
Köszi! Ha lesz egy kis időm meg fogom nézni! Mármint az egész boost-ot. Régóta rajta van a todo listámon, csak ritkán szoktam C++-ozni :( ...
- A hozzászóláshoz be kell jelentkezni
Kis darabonként kell haladni pont ezért..
- A hozzászóláshoz be kell jelentkezni
Csak kotozkodes: a drupal megette az #include sorokat, < > korbezaro a megoldas. (<stdio.h> = <stdio.h>)
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni