metoda běží na objekt před objekt byl inicializovat?

hlasů
1
#include <iostream>
using namespace std;

class Foo
{

public:

 Foo(): initialised(0)
 {
  cout << Foo() gets called AFTER test() ?! << endl;
 };

 Foo test()
 {
  cout << initialised=  << initialised <<  ?! - ;
  cout << but I expect it to be 0 from the 'initialised(0)' initialiser on Foo() << endl;
  cout << this method test() is clearly working on an uninitialised object ?! << endl;
  return Foo();
 }

 ~Foo()
 {};

private:

 int initialised;

};


int main()
{

 //SURE this is bad coding but it compiles and runs
 //I want my class to DETECT and THROW an error to prevent this type of coding
 //in other words how to catch it at run time and throw not initialised or something

 Foo foo=foo.test();

}
Položena 06/04/2009 v 22:38
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
5

Ano, to je volání funkce na dosud postavený objekt, který je definován chování. Není možné zjistit to spolehlivým. Chtěl bych vás argumentují také by neměla pokusit se odhalit. Není to nic, které by se stalo, pravděpodobně v důsledku nehody, oproti například volání funkce na již odstraněný objekt. Snaží chytit každý a všechny případné chyby je téměř nemožné. Jméno deklaroval je viditelný již v jeho inicializátor, pro jiné užitečné účely. Zvaž toto:

Type *t = (Type*)malloc(sizeof(*t)); 

Což je běžný idiom v programování v jazyce C, a který stále pracuje v jazyce C ++.

Osobně mám rád tento příběh o Herb Sutter referencí o null (což jsou rovněž neplatné). Podstatou je, nesnažte se chránit před případy, že jazyk jasně zakazuje, a zejména jsou ve svém obecném případě nelze diagnostikovat spolehlivě. Dostanete falešný bezpečnostní průběhu času, což se stává docela nebezpečné. Místo toho, vlak své znalosti jazyka a designu rozhraní způsobem (vyhýbejte se syrovým ukazatele, ...), který snižuje šanci dělat chyby.

V C ++ a podobně jako v C, v mnoha případech není výslovně zakázáno, ale spíše jsou ponechány definován. Částečně proto, že některé věci jsou poněkud obtížné diagnostikovat efektivně a částečně proto, že nedefinované chování nechává návrh alternativního chování implementace pro to místo úplně ignoroval to - který se používá často stávajícími překladačů.

Ve výše uvedeném případě například některý implementace je zatím výjimku. Existují i jiné situace, které jsou rovněž nedefinované chování, které jsou mnohem těžší diagnostikovat efektivně pro realizaci: mít objekt v jiném překladu jednotky přístupné před tím, než byl postaven je takový příklad - který je známý jako statická inicializace objednávky fiaskem .

Odpovězeno 06/04/2009 v 22:43
zdroj uživatelem

hlasů
2

Konstruktor je metoda, kterou chcete (neběží před inicializací, ale spíše na inicializaci, ale to by mělo být v pořádku). Důvod, proč to nefunguje ve vašem případě je to, že jste nedefinovaný chování zde.

Zvláště, můžete použít není dosud neexistující foo objekt inicializovat (např. fooV foo.Test()dosud neexistuje). Můžete vyřešit tím, že vytvoří objekt explicitně:

Foo foo=Foo().test()

Nemůžete kontrolovat ji v programu, ale možná valgrind nenašel tento typ chyby (jako jakýkoli jiný neinicializovanou přístupu do paměti).

Odpovězeno 06/04/2009 v 22:47
zdroj uživatelem

hlasů
1

Nemůžete zabránit lidem v kódování špatně , opravdu. Funguje to stejně jako to „má“:

  1. Přidělit paměť pro foo (což je hodnota „tohoto“ ukazatel)
  2. Chystáte se Foo :: zkoušku tím, že dělá: Foo :: testu (tento), v němž
  3. Dostane hodnotu tohle> inicializovat, což je náhodné junk, poté jej
  4. Volá Foo výchozí konstruktor (kvůli návratu foo ();), poté
  5. Volejte Foo kopírovací konstruktor, kopírovat pravotočivý foo ().

Stejně jako by měla. Nemůžete zabránit lidem nevěděl správný způsob, jak používat C ++.

Nejlepší věc, kterou může udělat, je mít magické číslo:

class A
{
public:
    A(void) :
    _magicFlag(1337)
    {
    }

    void some_method(void)
    {
        assert (_magicFlag == 1337); /* make sure the constructor has been called */
    }

private:
    unsigned _magicFlag;
}

Tato „práce“, protože je pravděpodobné, _magicFlag dostane přiděleno, kde je tato hodnota již 1337 je nízká.

Ale vážně, nedělej to.

Odpovězeno 06/04/2009 v 22:53
zdroj uživatelem

hlasů
0

Jste stále poměrně málo odpovědí, které v podstatě říkají, „neměli byste očekávat, že kompilátor, které vám pomohou s tím.“ Nicméně, já bych s vámi souhlasit, že překladač by měl pomoci s tímto problém s nějakou diagnostiku. Bohužel (jako ostatní odpovědi poukazují), jazyk spec nepomůže tady - jakmile se dostanete do Inicializátor části prohlášení nově deklarována identifikátor je v rozsahu.

Není to tak dávno, DDJ měl článek o jednoduchou třídu ladění s názvem „Dogtag“ , které by mohlo být použito jako pomoc při ladění pomoci s:

  • použití objektu po vypuštění
  • přepsání paměti objektu s odpady
  • použití objektu před jeho inicializaci

Osobně jsem nepoužil to moc - ale to přijde ručně dýhovaná na embedded projekt, který byl spuštěn v některých přepsání paměti chyb.

Je to v podstatě rozpracováním na „MagicFlag“ techniku, která Gman popsanou .

Odpovězeno 07/04/2009 v 00:15
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more