Forum » Programiranje » [C++] Dedovanje, virtualne in abstraktne metode
[C++] Dedovanje, virtualne in abstraktne metode
black ice ::
OOP mi kar naprej povzroča težave.
Kakšna je razlika med virtualno in abstraktno metodo?
Če si pravilno razlagam se virtualna metoda izvede le na koncu hierarhije (v izpeljanih razredih), če je tam ni se izvede tista v baznem razredu. Abstraktna metoda potemtakem nima implementacije v baznem razredu ampak samo v izpeljanih. Je pri obeh obvezno določilo virtual? Sprašujem zato, ker sem na netu zasledil primere v Javi, kjer je določilo abstract, pri C++ mi pa Eclipse javi napako, ko uporabim to določilo.
Spodaj imam en primer, ki ga skušam rešiti. Imam bazni oz. starševski razred Prenocisce iz katerega hočem (javno) izpeljati razreda HotelskaSoba in Apartma. Pri izpeljavi razreda HotelskaSoba ni nobenih težav, v razredu Apartma mi javi sledečo napako:
Še koda:
Kakšna je razlika med virtualno in abstraktno metodo?
Če si pravilno razlagam se virtualna metoda izvede le na koncu hierarhije (v izpeljanih razredih), če je tam ni se izvede tista v baznem razredu. Abstraktna metoda potemtakem nima implementacije v baznem razredu ampak samo v izpeljanih. Je pri obeh obvezno določilo virtual? Sprašujem zato, ker sem na netu zasledil primere v Javi, kjer je določilo abstract, pri C++ mi pa Eclipse javi napako, ko uporabim to določilo.
Spodaj imam en primer, ki ga skušam rešiti. Imam bazni oz. starševski razred Prenocisce iz katerega hočem (javno) izpeljati razreda HotelskaSoba in Apartma. Pri izpeljavi razreda HotelskaSoba ni nobenih težav, v razredu Apartma mi javi sledečo napako:
..\src\/Apartma.h:13:35: error: expected class-name before '{' token
Še koda:
#ifndef PRENOCISCE_H_ #define PRENOCISCE_H_ #include <string> namespace std { class Prenocisce { protected: string oznaka; public: Prenocisce(); virtual ~Prenocisce(); virtual void izpis(); virtual int vrni_ceno(); }; } /* namespace std */ #endif /* PRENOCISCE_H_ */
#ifndef HOTELSKASOBA_H_ #define HOTELSKASOBA_H_ namespace std { class HotelskaSoba : public Prenocisce { protected: int st_oseb; int cena_na_osebo; public: HotelskaSoba(); virtual ~HotelskaSoba(); }; } /* namespace std */ #endif /* HOTELSKASOBA_H_ */
#ifndef APARTMA_H_ #define APARTMA_H_ namespace std { class Apartma : public Prenocisce { protected: int cena; public: Apartma(); virtual ~Apartma(); }; } /* namespace std */ #endif /* APARTMA_H_ */
Something ::
V javi pred imenom razreda napišeš, da je razred abstrakten z rezervirano besedo abstract, v c++ pa tega ni. Razred je avtomatsko abstrakten, če vsebuje eno abstraktno metodo in to je taka, kjer samo napišeš = 0.
In ja pri abstraktni metodi je potrebtno tudi zapisat virtual.
Virtualna metoda pa pomeni, da če imaš kazalec, ki je tipa nadrazreda, kaže pa na kak njegov izpeljan razred, se bo klicala metoda izpeljanega razreda. Če pa metoda ni virtualna pa se bo vedno klicala metoda nadrazreda.
Pa v teh podrazredih moraš includat header od nadrazreda. Mislim, da ti zato javlja napako.
In ja pri abstraktni metodi je potrebtno tudi zapisat virtual.
Virtualna metoda pa pomeni, da če imaš kazalec, ki je tipa nadrazreda, kaže pa na kak njegov izpeljan razred, se bo klicala metoda izpeljanega razreda. Če pa metoda ni virtualna pa se bo vedno klicala metoda nadrazreda.
Pa v teh podrazredih moraš includat header od nadrazreda. Mislim, da ti zato javlja napako.
Something ::
Ker če destruktor ni virtualen, se lahko zgodi, da boš izbrisal samo tisti del razreda, ki je dedovan in ne celotnega.
Mesar ::
Oh I see now... http://www.gotw.ca/publications/mill18....
Avtorju... a maš #include "Prenocisce.h" ? Oz. ime .h fila v katerem je razred Prenocisce...
Avtorju... a maš #include "Prenocisce.h" ? Oz. ime .h fila v katerem je razred Prenocisce...
Your turn to burn!
Vesoljc ::
Kakšna je razlika med virtualno in abstraktno metodo?
virtual = you can
abstract = you must
Abnormal behavior of abnormal brain makes me normal...
Vesoljc ::
class base { public: virtual void foo1() { int dummy; } // virtual, you can override virtual void foo2() = 0; // pure virtual, abstract, you must implement }; class a : public base { public: void foo1() { base::foo1(); int mydummy; } // override and call base void foo2() { int mynew; } // just implement }; class b : public base { public: void foo1() { int nobase; } // implement, no base call void foo2() { int mynew; } // just implement };
Abnormal behavior of abnormal brain makes me normal...
mallard ::
Pa še:
#include <iostream> struct base { virtual void foo() = 0; // abstraktna metoda }; void base::foo() // ampak ima lahko implementacijo { std::cout << "Hey!"; } // base b; // <-- base je kljub temu abstrakten razred, to se ne prevede struct derived : base { virtual void foo() { base::foo(); } // kličemo implementacijo iz nadrazreda }; int main() { derived d; d.foo(); // Hey! }
black ice ::
Hvala za primere, mi je postalo malenkost bolj jasno.
Sem includal header izvornega razreda in se mi tista napaka več ne pojavlja, sedaj pa imam nekje semantično napako.
Sem includal header izvornega razreda in se mi tista napaka več ne pojavlja, sedaj pa imam nekje semantično napako.
Description Resource Path Location Type Symbol 'Prenocisce' could not be resolved Apartma.h /Vaja0601/src line 15 Semantic Error Symbol 'Prenocisce' could not be resolved HotelskaSoba.h /Vaja0601/src line 16 Semantic Error Symbol 'Prenocisce' could not be resolved HotelskaSoba.h /Vaja0601/src line 22 Semantic Error
#ifndef PRENOCISCE_H_ #define PRENOCISCE_H_ #include <string> #include <iostream> namespace std { class Prenocisce { protected: string oznaka; public: Prenocisce(string o) : oznaka(o) {} virtual ~Prenocisce() {} virtual void izpis() {} virtual int vrni_ceno() = 0; }; } /* namespace std */ #endif /* PRENOCISCE_H_ */
#ifndef HOTELSKASOBA_H_ #define HOTELSKASOBA_H_ #include <string> #include "Prenocisce.h" namespace std { class HotelskaSoba : public Prenocisce { protected: int st_oseb; int cena_na_osebo; public: HotelskaSoba (string o, int sto, int cno): Prenocisce(o), st_oseb(sto), cena_na_osebo(cno) {} virtual ~HotelskaSoba() {} void izpis() {cout << "St. oseb: " << st_oseb << " cena na osebo: " << cena_na_osebo;} int vrni_ceno() {return st_oseb*cena_na_osebo;} }; } /* namespace std */ #endif /* HOTELSKASOBA_H_ */
#ifndef APARTMA_H_ #define APARTMA_H_ #include "Prenocisce.h" #include <string> namespace std { class Apartma : public Prenocisce { protected: int cena; public: Apartma(int c): cena(c) {} virtual ~Apartma() {} void izpis() {cout << "Cena: " << cena;} }; } /* namespace std */ #endif /* APARTMA_H_ */
Mesar ::
Datoteka ja Prenocisce.h ali prenocisce.h? Imaš dodane datoteke v projekt?
Your turn to burn!
mallard ::
Zakaj postavljaš svoje razrede v namespace std? To samo kliče po težavah, std je rezerviran za implementacijo standardne knjižnice. V headerjih kvalificiraj imena iz standardne knjižnice, npr std::string, v cpp datotekah pa lahko rečeš "using namespace std;"
mallard ::
Pa v razredu Apartma moraš tudi implementirat abstraktno metodo vrni_ceno() iz prenočišča.
glede namespaca std:
glede namespaca std:
[C++11: 17.6.4.2.1/1]: The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.
Zgodovina sprememb…
- spremenilo: mallard ()
black ice ::
Glede pisanja razredov v namespace std: Eclipse ima možnost, da ti sam ustvari razrede in pripadajoče konstruktorje ter destruktorje.
mallard ::
Glede pisanja razredov v namespace std: Eclipse ima možnost, da ti sam ustvari razrede in pripadajoče konstruktorje ter destruktorje.
Nisem prepričan, če se razumeva. Razredi so že v redu nastavljeni, ampak ne bi smeli bit definirani v namespace-u std, ampak v kakem drugem, npr. moj_nejmspejs, moj_std ali karkoli že. Če ti eclipse nastavi namespace std, potem se mu mal blede :)
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Java program (strani: 1 2 )Oddelek: Programiranje | 8496 (7645) | kunigunda |
» | Pomoč pri programiranju v C++Oddelek: Programiranje | 1801 (1368) | amacar |
» | Iščem program c++Oddelek: Programiranje | 853 (721) | krneki0001 |
» | [C++] Linker errorOddelek: Programiranje | 1280 (1280) | Quikee |
» | [C++] Problem z dedovanjem šablon (template inhieritance)Oddelek: Programiranje | 1643 (1521) | Gundolf |