Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Polimorfizm, Dziedziczenie i klasy abstrakcyjne.

Ostatnio zmodyfikowano 2014-06-13 23:41
Autor Wiadomość
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
P-112040
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.
P-112041
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
P-112042
Jacob99
» 2014-06-13 23:09:02
Możesz wykorzystać na przykład szablony funkcji.
P-112043
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
P-112046
« 1 »
  Strona 1 z 1