[c++] klasy wewnetrzne dziedziczenie i szblony naraz :)

0

#include <iostream>

template<typename T> class Base {

  public:
    typedef T value_type;

    Base(T value) : cosik(value) {}

    T returning() {
    	return cosik;
    }

    class Inner1 {
      public:
        Inner1(int l) : liczba(l) {}

      protected:
	int liczba;

    };

    class Inner2 : public Inner1 {
      public:
  	int zwracam() {
	  return liczba;
	}
    };

 private:
   T cosik; 
};

int main() {

  Base<int> b1(5);

}

g++ mowi że Inner2 nie zna pola liczba, ale przeciez dziedziczy klase ktora je zawiera ;/

0

spróbuj this->liczba

0

Inner jest symbolem/nazwą zalezną od konkretyzacji szablonu. zamien 'Inner' na typename Base<T>::Inner i pewnie kompilator sie zgodzi ze masz racje

0
quetzalcoatl napisał(a)

Inner jest symbolem/nazwą zalezną od konkretyzacji szablonu. zamien 'Inner' na typename Base<T>::Inner i pewnie kompilator sie zgodzi ze masz racje

wtf? gdzie ma to niby wstawić? poprzednie rozwiązanie jest najlepszym możliwym..
jak się chce inaczej można jeszcze:

  class Inner2 : public Inner1 {
      public:
    using Base<T>::Inner1::liczba; //to zdaje sie robi liczbe publiczna? ale pewien nie jestem
    Inner2() : Inner1(0) {} //a o tym autor kodu zapomnial
    int zwracam() {
      return liczba;
        }
    };

bądz też napisanie "return Inner1::liczba"

Podsumowując - najlepszym rozwiązaniem jest this->.
A bez niczego kompilator po prostu szuka symbolu w przestrzeni bez klasy Base (i przez to Inner)

0

disclaimer: nie mam okazji wlaczyc kompilatora g++ ani nawet msvc zeyb sprawdzic to co napisalem i zaraz napisze, stad jest to obecny moj domysl
disclaimer2: pomijam public/private/protected - oczywiste

nie widze powodu dlaczego kompilator, KTORY ZAUWAZYL ze Inner2 jest pochodna Inner, niemialy zauwazac ze Inner2 zawiera pole liczba. Przeciez to zwykle dziedziczenie! jesli jest w stanie znalezc klase Inner, to zna jej pola skladowe, wiec nie powinien miec problemu.

zuooo napisał(a)

A bez niczego kompilator po prostu szuka symbolu w przestrzeni bez klasy Base (i przez to Inner)

jesli tak jest, to w przypadku:

class X
{
   class Y { int blah; }
   class Z : Y { Z() { blah = 5; } }
}

klasa Z tez by ni ewidziala pola blah --- nigdy tego zachowania nie zauwazylem...


moim zdaniem, problem tkwi w tym, ze Base jest szablonem i zapis Inner2 : Inner jest niejednoznaczny. sadze ze kompilator NIE WIDZI klasy Inner tak jak powinien.

"Inner" jest faktycznie "Base<T>::Inner" i nie jest wiadome czy chodzi o to samo <T> w 'zakresie' ktorego jest deklarowane Inner2 czy o inne -- calkowicie legalne przeciez byloby:

A<double>::C cos;  gdzie:
template <T> class A{
    class B{ T x; }
    class C : A<int>::B {};   // dla B T:=int a nie double!
    class C : B {};   // A<..?..> ::B
}

stad, domyslam sie, ze w ramach poprawki wystarczy:

template<T> class Base{
    class Inner {}
    class Inner2 : Base<T>::Inner {}
}

przyczym, mozliwe przeciez jest takze:
template <T> class A{
class B{ T x; }
class C : B {};
}

template <> class A<int> { //specjalizacja szablonu klasy A dla int'a - nie posiadajaca B ani C
class X {}
}
</cpp>

wiec wyraznie B i C sa symbolami zaleznymi, ktore dopiero w konkretyzacji szablonu sie ujawnia albo okaza nieistniejace!

stad moj pomysl na naprawienie brzmi:

 template<T> class Base{
    class Inner {}
    class Inner2 : typename Base<T>::Inner {}
}

co przyznam, nie wiem czy jest w 100% skladniowo poprawne, ale tak ja bym to widzial.


edit: zostawiam zamieszczony tok myslenia, ale -- szukajac dalej, natrafilem na: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18 co dokladnie opisuje ten przypadek.

to co podal zuoooo jest wlasciwe. problem rzeczywiscie, tak jak sadzilem, tkwi w dependent/nondependent names, ale nie Inner/Inner2 jak sadzilem -- tylko faktycznie w samym "liczba".
cytujac mozliwe poprawki, wystarczy zamienic symbol "liczba" na jedno z :

  1. taka jak podal uuuu: ---------- this->liczba
  2. taka jak podal zuooo: ---------- using Base<T>::liczba
  3. taka jak podalem, ale gdzie indziej :) ---------- Base<T>::liczba
0
quetzalcoatl napisał(a)

klasa Z tez by ni ewidziala pola blah --- nigdy tego zachowania nie zauwazylem...

moim zdaniem, problem tkwi w tym, ze Base jest szablonem i zapis Inner2 : Inner jest niejednoznaczny. sadze ze kompilator NIE WIDZI klasy Inner tak jak powinien.

Tak - przez to że jest szablonem nie istnieje w pierwszej fazie rozwijania symboli, nie chodziło mi oczywiście o wszystkie (nie templateowane) klasy.

 template<T> class Base{
    class Inner {}
    class Inner2 : typename Base<T>::Inner {}
}

co przyznam, nie wiem czy jest w 100% skladniowo poprawne, ale tak ja bym to widzial.

Nie jest, co to by miało robić? Typy dziedziczące są zawsze typami, inaczej by to sensu nie miało.

edit: zostawiam zamieszczony tok myslenia, ale -- szukajac dalej, natrafilem na: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18 co dokladnie opisuje ten przypadek.

to co podal zuoooo jest wlasciwe. problem rzeczywiscie, tak jak sadzilem, tkwi w dependent/nondependent names, ale nie Inner/Inner2 jak sadzilem -- tylko faktycznie w samym "liczba".
cytujac mozliwe poprawki, wystarczy zamienic symbol "liczba" na jedno z :

  1. taka jak podal uuuu: ---------- this->liczba
  2. taka jak podal zuooo: ---------- using Base<T>::liczba
  3. taka jak podalem, ale gdzie indziej :) ---------- Base<T>::liczba

To ostatnie tak średnio - a jak zmienisz nazwę superklasy? Tworzysz sobie dodatkowe zależności w kodzie. (i po co to Base<T> ? Samo Inner starczy.)

(btw uuuu = zuooo)

0

Nie jest, co to by miało robić? Typy dziedziczące są zawsze typami, inaczej by to sensu nie miało.

zgadzam sie. jak juz napisalem, pomylilem ktory symbol zalezny jest "niewidziany". myslalem ze jest to "Inner2" natomiast jest nim "liczba". a skoro myslalem o wskazywaniu typu zaleznego, typename.

To ostatnie tak średnio - a jak zmienisz nazwę superklasy? Tworzysz sobie dodatkowe zależności w kodzie. (i po co to Base<T> ? Samo Inner starczy.)

rozwiazania jakie sa, takie sa. albo 1) albo 2) albo 3), wszystkie sa rownorzedne. 1) jest najlepsza, dwojka srednia, i tak, 3) robi zaleznosc, ale takie sa mozliwosci i nawet sa one wymienione na parashifcie.
gwoli scislosci: wymienilem je, poniewaz 1/2 juz podaliscie, a 3 to bylo to o czym ja pomyslalem. a to ze (pierwotnie) wpakowalem Base<T>::Inner w nie to miejsce co powinienem byl, to inna sprawa :)

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