C++ a přidání „členské proměnné“

Waseihou

C++ a přidání „členské proměnné“
« kdy: 22. 06. 2012, 12:39:03 »
1) Dejme tomu, že máme situaci, kdy máme nějaký C++ objekt v nějaké knihovně od kterého jsou poděděny objekty v jiných knihovnách, a potřebujeme přidat členskou proměnnou do tohoto objektu. Problémem ale je že máme zakázáno přidat členskou proměnnou, protože by to znamenalo rekompilaci všech závislostí. Jaké možnosti máme, a existuje nějaké elegantní řešení tohoto problému?

Napadá mě třeba:

Kód: [Vybrat]
.hxx:

class Object{
public:
//...
  void call();
private:
    int m_val1;
    // void *m_handle; // tohle nemůžeme, změnila by se velikost instance Object
};

.cxx:
void Object:call() {
  // tady potřebujeme inicializovat m_handle, aby se třeba nějaký zdroj zde získaný mohl později uvolnit
  // ale bohužel nemůžeme přidat členskou proměnnou
}

2) dejme tomu, že můžeme provést právě jednu změnu v onom headeru (další bude povolena třeba až za dva roky...)
a) Jak nejlépe připravit objekt pro případ že by se daná situace s členskými proměnnými opakovala?
b) Jak vyřešit situaci kdy bychom chtěli přidat metodu která může mít různý počet parametrů, ale opět nebude moci změnit header?  Je tohoto možno dosáhnout dynamicky bez rekompilace objekt (klient přihodí metodu která je potřeba přímo do instance objektu). Řešení může obsahovat nějaký call jiné metody jakp Object::Call(const char*, ...) => obj->call("nova_fce",param1,param2,param3,NULL);
« Poslední změna: 22. 06. 2012, 13:49:09 od Petr Krčmář »


Waseihou

Re:C++ - přidání "členské proměnné" bez nutnosti změnit header
« Odpověď #1 kdy: 22. 06. 2012, 12:43:08 »
Jo a k tomu nápadu jsem ho zapomě dopsat:

takže udělá se std::map<unsigned long, void*> g_data;

a v kostruktoru: g_data[(unsigned long)this] = (void*) new SomeObject();


a tam kde to je potřeba najít podle this příslušná data

SomeObject *p = dynamic_cast<SomeObject*>(g_data[(unsigned long)this]);
if (p) {...}

nebo něco na ten způsob, nenapadá někoho lepší řešení?

broukoid

Re:C++ - přidání "členské proměnné" bez nutnosti změnit header
« Odpověď #2 kdy: 22. 06. 2012, 13:35:01 »
reseni me napada, ale asi ho nebudete chtit slyset: zmente zamestnavatele

Sten Fil

Re:C++ a přidání „členské proměnné“
« Odpověď #3 kdy: 22. 06. 2012, 14:32:04 »
2.a
Mrkni na C++ PIMPL. Elegantne to resi.

Waseihou

Re:C++ a přidání „členské proměnné“
« Odpověď #4 kdy: 22. 06. 2012, 15:20:44 »
PIMPL znám, otázkou jestli jde implementovat nějak elegantně a nebo stačí opravdu jen ten pointer

Co kdybych měl hierarchii objektů které dědí z jednoho společného a "sdílí" tento problém a v každém z nich může nastat situace kdy je třeba přidat member?

Napadá mě použít nějaké to std::map<std::string class, void *pimpl> m_pImpls; jako protected a pak by každý objekt měl svůj PIMPL, tedy třeba objekt typu CEditField by měl pimpl a lá:

CEditField() { struct members_s *m = (struct members_s*)m_pImpls["CEditFields"]; m->handleIcon = new Data(); m->val1 = 5; m->val2 = 10;}

~CEditField() { struct members_s *m = (struct members_s*)m_pImpls["CEditFields"]; delete m; }

a možná pro ty srandy s deklaracemi m by šla udělat nějaká template která by to udělala hezký


Re:C++ a přidání „členské proměnné“
« Odpověď #5 kdy: 22. 06. 2012, 17:55:46 »
Co je na PIMPL neelegantni? :-) Neni problem do kazde tridy pridat ukazatel na Private tridu, i kdyz by ta Private trida byla (zatim) prazdna.

Normalne staci jen pointer, ale hodi se jeste friend class MyClassPrivate (aby vam trida mohla volat privatni/protected funkce, pokud je zakladni trida ma) a

Kód: [Vybrat]
MyClassPrivate * const d_func() const
abyste mohl pristupovat k te private tride i v const metodach.

V Qt je na tohle pekne makro Q_DECLARE_PRIVATE(class_name), ktere to automaticky generuje a vypada to otrosku hezceji :-)


Ad 2b) - pridani nove metody do tridy nerozbiji ABI (nema vliv na velikost struktury). Nemuzete ale pretizit nepretizenou metodu (pokud uz je metoda alespon jednou pretizena, muzete v klidu pridat dalsi pretezujici metodu), nemuzete pridat virtualni funkci a reimplementovat virtualni funkci, pokud uz ji nektery z predku implementuje.