marcin022 Temat założony przez niniejszego użytkownika |
Polimorfizm, Dziedziczenie i klasy abstrakcyjne. » 2014-06-13 22:13:31 Witam mam problem z zadaniem do szkoly. Stworzylem abstrakcyjna klase bryla i czysto wirtualne funkcje. W programie chce użyć późnego wiązania. Wcześniej napisałem prawie identyczny program jako zadanie do szkoly ale z dużo prostsza struktura obiektów i wszystko działało. Oto mój kod
#include <iostream> #include<cmath> using namespace std; class Bryla{ public: virtual double objetosc()=0; virtual double pole_powierzchni_calkowitej()=0; virtual void pobierz_dane()=0; virtual ~Bryla(){;} };
class Stozek : public Bryla{ protected: double promien; double wysokosc; double wodzacy;
public: Stozek(){} double pole_powierzchni_calkowitej(); double objetosc(); void pobierz_dane(double promien, double wysokosc, double wodzacy); }; class Walec : public Stozek{ public: double pole_powierzchni_calkowitej(); double objetosc(); void pobierz_dane(double promien, double wysokosc); }; class Czworoscian : public Bryla { protected: double a; double wysokosc; public: double pole_powierzchni_calkowitej(); double objetosc(); void pobierz_dane(double, double); }; class Prostopadloscian : public Czworoscian { double b; public: double pole_powierzchni_calkowitej(); double objetosc(); void pobierz_dane(double, double, double); }; void Pobierz(Bryla *wsk) { wsk->pobierz_dane(); }
int main(){ Bryla *wsk; Stozek s1;
system("pause"); return 0; }
void Stozek :: pobierz_dane(double r, double h, double l ) { cout<<"promien: "; cin>>r; cout<<",wysokosc: "; cin>>h; cout<<",promien wodzący: "; cin>>l; this->promien=r; this->wysokosc=h; this->wodzacy=l;
}
double Stozek :: pole_powierzchni_calkowitej() { return (3.14 * pow(promien,2) + 3.14 * promien * wodzacy); } double Stozek :: objetosc() { return (3*14 * pow(promien,2))/3; }
void Walec :: pobierz_dane(double r, double h) { this->promien=r; this->wysokosc=h; }
double Walec :: objetosc() { return (3.14 * pow(promien,2) * wysokosc); } double Walec :: pole_powierzchni_calkowitej() { return ((2*3,14*pow(promien,2)+(2*3.14*wysokosc))); }
void Czworoscian :: pobierz_dane(double a, double wysokosc) { this->a=a; this->wysokosc=wysokosc; } double Czworoscian :: objetosc() { return (((a*sqrt(3)/4)*wysokosc)/3); } double Czworoscian :: pole_powierzchni_calkowitej() { return (pow(a,2)*sqrt(3)); }
void Prostopadloscian :: pobierz_dane(double a, double b, double h) { this->a=a; this->b=b; this->wysokosc=h; } double Prostopadloscian :: objetosc() { return (a*b*wysokosc); } double Prostopadloscian :: pole_powierzchni_calkowitej() { return (2*a*b+2*b*wysokosc+2*a*wysokosc); }
a to komunikat o błędzie kompilacji Error 1 error C2259: 'Stozek' : cannot instantiate abstract class c:\users\marcin\desktop\wspolne bis\metody programowania (sem. 2)\zaliczenie2\klasyabstrakcyjne\klasyabstrakcyjne\source.cpp 56 1 klasyabstrakcyjne 2 IntelliSense: object of abstract class type "Stozek" is not allowed: pure virtual function "Bryla::pobierz_dane" has no overrider c:\Users\Marcin\Desktop\Wspolne Bis\METODY PROGRAMOWANIA (SEM. 2)\zaliczenie2\klasyabstrakcyjne\klasyabstrakcyjne\Source.cpp 56 9 klasyabstrakcyjne
Prosze o pomoc bo już zgłupiałem |
|
Jacob99 |
» 2014-06-13 22:40:28 Stworzyłeś w klasie Bryla wirtualną funkcję z której nie korystasz. Aby funkcja wirtualna była tą samą funkcją we wszystkich klasach pochodnych musi być całkowicie zgodna ze swoją deklaracją w klasie bazowej. Oznacza to, że we wszystkich klasach pochodnych funkcja musi zwracać ten sam typ i przyjmować te same argumenty. Pisząc w klasie Bryla taką deklarację virtual void pobierz_dane() = 0; tworzysz: wirtualną funkcję pobierz_dane nieprzyjmującą żadnych argumentów i nic nie zwracającą. Z kolei w klasie dziedzicznej stożek pisząc void pobierz_dane( double promien, double wysokosc, double wodzacy ); tworzysz funkcję pobierz_dane przyjmującą 3 argumenty typu double i nic niezwracającą. Innymi słowy: zamiast odpowiednika wirtualnej funkcji pobierz_dane z klasy Bryla tworzysz nową funkcję. To się nazywa przesilenie nazwy funkcji. Ponieważ robisz to we wszystkich klasach dziedzicznych czysto wirtualna funkcja pobierz_dane nie ma następcy w klasach dziedzicznych i jest to błąd w języku C++. O tym właśnie informuje cię ten komunikat IntelliSense: object of abstract class type "Stozek" is not allowed: pure virtual function "Bryla::pobierz_dane" has no overrider c:\Users\Marcin\Desktop\Wspolne Bis\METODY PROGRAMOWANIA (SEM. 2)\zaliczenie2\klasyabstrakcyjne\klasyabstrakcyjne\Source.cpp 56 9 klasyabstrakcyjne
który oznacza po prostu, że (ponieważ próbujesz to zrobić w funkcji main) nie można stworzyć obiektu abstrakcyjnej klasy stożek.Skoro nie zdefiniowałeś w niej następcy funkcji wirtualnej to ta klasa jest abstrakcyjna. |
|
marcin022 Temat założony przez niniejszego użytkownika |
» 2014-06-13 23:06:01 Czyli zle zrozumialem istote funkcji wirtualnej a poprzedni program dzialal bo mial identyczna definicje we wszystkich klasach pochodnych zwracal void i nic nie przyjmowal jako argument bo mial na celu jedynie wypisanie wartosci chronionych. Teraz zastanawiam sie jak to obejsc. czy moge przeciazyc nazwe funkcji wirtualnej i zrobic kilka deklaracji dla roznych typow zwracanych wartosci?. Jak deklaruje to w ten sposob ze jako argumenty przesylam 3 razy double to VS krzyczy ze ze funkcja nie przyjmuje 0 argumentow i tutaj chyba musze wrocic do podstaw |
|
Jacob99 |
» 2014-06-13 23:09:02 Możesz wykorzystać na przykład szablony funkcji. |
|
marcin022 Temat założony przez niniejszego użytkownika |
» 2014-06-13 23:41:01 Dzięki twojej pomocy merytorycznej w zrozumieniu ograniczen nalożonych na funkcje wirtualne i po odbyciu bolesnej konfrontacji wspanialych wybrazen na ich temat a rzeczywistoscia stworzylem nadal zgodny z zalozeniami programy poprawiony kod
#include <iostream> #include<cmath> using namespace std; class Bryla{ public: virtual double objetosc()=0; virtual double pole_powierzchni_calkowitej()=0; virtual void pobierz_dane()=0;
virtual ~Bryla(){;} };
class Stozek : public Bryla{ protected: double promien; double wysokosc; double wodzacy;
public: Stozek(){} double pole_powierzchni_calkowitej(); double objetosc(); void pobierz_dane(); }; class Walec : public Stozek{ public: double pole_powierzchni_calkowitej(); double objetosc(); void pobierz_dane(); }; class Czworoscian : public Bryla { protected: double a; double wysokosc; public: double pole_powierzchni_calkowitej(); double objetosc(); void pobierz_dane(); }; class Prostopadloscian : public Czworoscian { double b; public: double pole_powierzchni_calkowitej(); double objetosc(); void pobierz_dane(); }; void Pobierz(Bryla *wsk) { wsk->pobierz_dane(); } double Objetosc(Bryla *wsk) { return wsk->objetosc(); } double Pole(Bryla *wsk) { return wsk->pole_powierzchni_calkowitej(); }
int main(){ Bryla *wsk; Stozek s1; wsk = &s1; Pobierz(wsk); cout<<endl<<"Objetosc: "<<Objetosc(wsk)<<", pole pow calko: "<<Pole(wsk); cout<<endl; system("pause"); return 0; }
void Stozek :: pobierz_dane() { cout<< endl<<"promien: "; cin>>promien; cout<<",wysokosc: "; cin>>wysokosc; cout<<",promien wodzący: "; cin>>wodzacy;
}
double Stozek :: pole_powierzchni_calkowitej() { return (3.14 * pow(promien,2) + 3.14 * promien * wodzacy); } double Stozek :: objetosc() { return (3*14 * pow(promien,2))/3; }
void Walec :: pobierz_dane() { cout<< endl<<"Podaj promien: "; cin>>promien; cout<<"Podaj wysokosc: "; cin>>wysokosc; }
double Walec :: objetosc() { return (3.14 * pow(promien,2) * wysokosc); } double Walec :: pole_powierzchni_calkowitej() { return ((2*3,14*pow(promien,2)+(2*3.14*wysokosc))); }
void Czworoscian :: pobierz_dane() { cout<<endl <<"Podaj dlugość boku: "; cin>>a; cout<<", podaj wysokosc: "; cin>>wysokosc; } double Czworoscian :: objetosc() { return (((a*sqrt(3)/4)*wysokosc)/3); } double Czworoscian :: pole_powierzchni_calkowitej() { return (pow(a,2)*sqrt(3)); }
void Prostopadloscian :: pobierz_dane() { cout<<endl <<"podaj dl boku a: "; cin>>a; cout<<", podaj dl boku b: "; cin>>b; cout<<", podaj wysokosc: "; cin>>wysokosc; } double Prostopadloscian :: objetosc() { return (a*b*wysokosc); } double Prostopadloscian :: pole_powierzchni_calkowitej() { return (2*a*b+2*b*wysokosc+2*a*wysokosc); }
Metoda pobierz_dane musiala pozostac wirtualna i taka jest zmienilem tylko sposob przekazywania wartosci z metody do chronionych obiektów. Szacunek i pozdrawiam |
|
« 1 » |