Jak předat výsledek metody jako parametr base konstruktoru třídy v C ++?

hlasů
2

Já jsem se snaží dosáhnout něčeho takového:

class Base
{
  public:

  Base(string S) 
  {
  ...
  };
}

class Derived: Base
{
public:
  int foo;
  string bar()
  {
    return stringof(foo); // actually, something more complex
  };

  Derived(int f) : foo(f), Base(bar()) 
  {
  };
}

Nyní, to nefunguje tak, jak chci, protože bar () je volána v odvozené konstruktoru před foo je inicializována.

Považoval jsem přidání statického funkci podobnou bar (), která bere v foo jako parametr - a používání, že v seznamu inicializace, ale myslel, že bych se zeptat, jestli tam byly nějaké jiné techniky, které by mohly být použity k kopat sebe ven z tohoto jednoho. ..

Edit : Díky za zpětnou vazbu - tady je návod, jak jsem chtěl zvládnout statickou funkci. Není si jistý, jestli přetížení mezi statickou a non-statické funkce je příliš chytrý, ale ...

class Derived: Base
{
public:
  int foo;

  static string bar(int f)
  {
    return stringof(f); // actually, something more complex
  }

  string bar()
  {
    return bar(foo); 
  };

  Derived(int f) :  Base(bar(f)) , foo(f)
  {
  };
}
Položena 17/12/2008 v 17:31
zdroj uživatelem
V jiných jazycích...                            


6 odpovědí

hlasů
4

Můžete volat pouze statické funkce v seznamu Inicializátor. To, jak ji máte ve svém kódu:

class Derived: Base
{
public:
  int foo;
  string bar()
  {
    return stringof(foo); // actually, something more complex
  };

  Derived(int f) : foo(f), Base(bar()) 
  {
  };
}

Bude i nadále inicializovat základny a teprve potom foo. Pořadí, jak píšete, co v seznamu konstruktor Inicializátor nezáleží na tom, v žádném případě. To bude vždy postavit v tomto pořadí:

  1. Za prvé, všechny základní třídy virtuálních
  2. Potom non-virtuální základní třídy v pořadí, v jakém jsou uvedeny v seznamu bází tříd
  3. Pak všechny členské objekty v pořadí, v jakém jsou definovány v definici třídy.

Takže jste skončili volání stringofs neinicializovanou hodnotou. Tento problém je vyřešen v boost::base_from_member. Také si všimněte, že volání do všech nonstatic funkce členů přede všemi konstruktoru Inicializátory všech bází třídy dokončených není definováno chování.

Volání statické funkce, ale je zcela v pořádku:

class Derived: Base
{
public:
  int foo;
  static string bar(int f)
  {
    return stringof(f); // actually, something more complex
  };

  Derived(int f) : Base(bar(f)), foo(f)
  {
  };
}
Odpovězeno 17/12/2008 v 17:42
zdroj uživatelem

hlasů
4

Ano, s použitím funkce (statické metody třídy nebo pravidelné funkce), který bere v foo jako parametr a vrátí řetězec je dobrým řešením. Můžete volat tuto stejnou funkci z odvozených :: baru, aby se zabránilo zdvojení kódu. Takže vaše konstruktor bude vypadat takto:

Derived(int f) : Base(stringof(f)), foo(f) {}

I umístit hovor do základny konstruktoru první v seznamu zdůraznit pořadí, ve kterém nastanou inicializace. Uspořádání seznamu Inicializátor nemá žádný vliv, protože všechny členy třídy jsou inicializovány v pořadí, v jakém jsou deklarovány ve třídě těle.

Jedná se o velmi čistý, funkční přístup k problému. Pokud však přesto chtěli vážit alternativy pak zvážit použití prostředku namísto dědičnosti pro vztah mezi odvozenou a báze tříd:

class Base {
public:
    Base(string S) {  ...  }
    void bat() { ... }
};

class Derived {
    Base *base;
    int foo;

public:
    Derived(int f) : base(NULL), foo(f) {
        base = new Base(bar());
    }
    ~Derived() {
        delete base;
    }

    string bar() {
        return stringof(foo); // actually, something more complex
    }

    void bat() {
        base->bat();
    }
};

Budete muset zvážit výhody a nevýhody pro vaši konkrétní situaci. S Odvozená drží odkaz na základně získáte větší kontrolu nad pořadí inicializace.

Odpovězeno 17/12/2008 v 17:38
zdroj uživatelem

hlasů
2

Základní třída konstruktor vždy volána před inicializaci ostatní členy odvozené třídě; váš kompilátor by mělo být, že vám varování pro mít inicializátory v nesprávném pořadí. Jediným správným řešením je, aby se bar()statickou metodu, která bere fjako parametr.

Odpovězeno 17/12/2008 v 17:44
zdroj uživatelem

hlasů
1

Konstruktor je pro dobře, konstrukci objektu. To znamená, že až se vrátí, není tam objekt, a proto, že volání funkce členů prostě nebude fungovat spolehlivě. Stejně jako všichni ostatní tvrdí, použijte statickou funkci nebo funkci nečlenskou.

Odpovězeno 17/12/2008 v 17:54
zdroj uživatelem

hlasů
0

Jen přesunout kurzor konstruktoru kód funkcí Initialize () a volání z konstruktoru. To je mnohem jednodušší, než statické / nonstatic najetí vozidel nebo něco podobného.

Odpovězeno 17/12/2008 v 18:31
zdroj uživatelem

hlasů
0

Chtěl jsem to udělat stejně, ale jsem to vzdal na konci.
Jakýkoliv vhodný volání funkce by mohla být použita jako parametr báze ().
Další možností je přidat a alternativní konstruktér k základně, která bere int a dělá konverze na ‚řetězec‘ sám.

Odpovězeno 17/12/2008 v 17:41
zdroj uživatelem

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