mboost-dp1
Problemer med polymorfisme i C++
- Forside
- ⟨
- Forum
- ⟨
- Programmering
Hejsa. Som nævnt i overskriften har jeg lidt bøvl med polymorfisme i C++. Følgende program demonstrerer mit problem:
Programmet outputter "Base", men jeg vil gerne have den til at outputte "Derived".
Jeg har en mistanke om, at problemet opstår, fordi det på en eller anden måde er Base's copy constructor, som bliver kaldt i linje 17, men jeg ved det ikke.
Problemet kunne formentlig løses ved at bruge pointere direkte, dvs. noget bruge noget a la std::vector<Base*>, men det vil jeg helst undgå, hvis det er muligt.
Hvad skal jeg gøre?
#include <iostream>
#include <vector>
class Base {
public:
virtual void print() {std::cout << "Base\n";}
};
class Derived : public Base {
public:
void print() {std::cout << "Derived\n";}
};
int main(int argc, char* argv[]) {
std::vector<Base> v;
v.push_back(Derived());
v.at(0).print();
}
Programmet outputter "Base", men jeg vil gerne have den til at outputte "Derived".
Jeg har en mistanke om, at problemet opstår, fordi det på en eller anden måde er Base's copy constructor, som bliver kaldt i linje 17, men jeg ved det ikke.
Problemet kunne formentlig løses ved at bruge pointere direkte, dvs. noget bruge noget a la std::vector<Base*>, men det vil jeg helst undgå, hvis det er muligt.
Hvad skal jeg gøre?
Du skal bruge pointere for at opnå det du prøver på.
Det der sker er at dit Derived-object bliver kopieret til et Base objekt i linie 17 og det vil aldrig ske fordi du kommer en kopi ind i din vector.
Hvis du derimod laver en vector med Base*, så kan du sætte en pointer til et Derived-objekt ind i din vector.
Det er i øvrigt pænest at sætte virtual på den nye funktion.
Det der sker er at dit Derived-object bliver kopieret til et Base objekt i linie 17 og det vil aldrig ske fordi du kommer en kopi ind i din vector.
Hvis du derimod laver en vector med Base*, så kan du sætte en pointer til et Derived-objekt ind i din vector.
Det er i øvrigt pænest at sætte virtual på den nye funktion.
#include <iostream>
#include <vector>
class Base {
public:
virtual void print() {std::cout << "Base\n";}
};
class Derived : public Base {
public:
virtual void print() {std::cout << "Derived\n";}
};
int main(int argc, char* argv[]) {
std::vector<Base *> v;
v.push_back(new Derived());
v.at(0)->print();
}
#3
Jeps :) Kan godt se jeg kunne have svaret bedre.
Jeg gætter på grunden til du helst ville undgå pointere, var for at slippe for skulle sørge for at slette dem efter brug.
Jeg ved ikke om du kender til smart pointers, men de vil løse det problem.
En smart pointer er en wrapper om en pointer til dit objekt som holder styr på hvor mange gange dit objekt er referet. Når sidste reference til objekted forsvinder bliver objektet slettet fra RAM.
Jeg plejer at bruge boosts shared_ptr da disse er meget nemme at bruge.
Det eneste det kræver er at man har boost installeret ved compile time, så man har deres headers tilrådighed (brugeren skal ikke have boost installeret for at køre programmet).
De fleste linux distriutioner har boost i deres pakkemanager, windows ved jeg ikke hvordan man installere men det skulle være nemt nok.
For at gøre det nemmere at forstå hvad jeg snakker om har jeg skrevet dit eksempel om, så det gør brug af arv og shared_ptr.
Boosts hjemmeside http://www.boost.org/
Jeps :) Kan godt se jeg kunne have svaret bedre.
Jeg gætter på grunden til du helst ville undgå pointere, var for at slippe for skulle sørge for at slette dem efter brug.
Jeg ved ikke om du kender til smart pointers, men de vil løse det problem.
En smart pointer er en wrapper om en pointer til dit objekt som holder styr på hvor mange gange dit objekt er referet. Når sidste reference til objekted forsvinder bliver objektet slettet fra RAM.
Jeg plejer at bruge boosts shared_ptr da disse er meget nemme at bruge.
Det eneste det kræver er at man har boost installeret ved compile time, så man har deres headers tilrådighed (brugeren skal ikke have boost installeret for at køre programmet).
De fleste linux distriutioner har boost i deres pakkemanager, windows ved jeg ikke hvordan man installere men det skulle være nemt nok.
For at gøre det nemmere at forstå hvad jeg snakker om har jeg skrevet dit eksempel om, så det gør brug af arv og shared_ptr.
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
class Base {
public:
virtual void print() {std::cout << "Base\n";}
};
class Derived : public Base {
public:
virtual void print() {std::cout << "Derived\n";}
};
int main(int argc, char* argv[]) {
std::vector< boost::shared_ptr< Base > > v;
// Add derived object to our vector
Derived * d_ptr = new Derived( ); // Create a pointer to a Derived-object. this can be merged with the next line.
boost::shared_ptr<Base> d( d_ptr ); // Wrap the pointer in shared_ptr
v.push_back(d); // Add the wrapped pointer to the vector
// Should print "Derived"
v.at(0)->print();
// Print how many times d_ptr is used, should to 2
std::cout << d.use_count( ) << std::endl;
// Empty the vector to remove one reference to d
v.clear( );
// Print how many times d_ptr is used, should to 1
std::cout << d.use_count( ) << std::endl;
// Once this function goes out of scope d will be deleted and since use_count hits 0 d_ptr will also deleted.
}
Boosts hjemmeside http://www.boost.org/
#4
Lige præcis. Dels for at pointere kan være trælse at holde styr på, og dels for at det gør koden mindre læsbar.
Ja, jeg kender lidt til smart pointers (i form af auto_ptr - ikke den fra Boost), men har ikke prøvet at bruge dem i praksis endnu.
Som du nok kan fornemme, så er jeg ikke superfortrolig med C++ endnu - jeg trækker rigtig meget på mine erfaringer fra andre programmeringssprog (f.eks. kendskab til de mange begreber, osv), så det går forholdsvist hurtigt og smertefrit med at sætte sig ind i C++. :-)
Lige præcis. Dels for at pointere kan være trælse at holde styr på, og dels for at det gør koden mindre læsbar.
Ja, jeg kender lidt til smart pointers (i form af auto_ptr - ikke den fra Boost), men har ikke prøvet at bruge dem i praksis endnu.
Som du nok kan fornemme, så er jeg ikke superfortrolig med C++ endnu - jeg trækker rigtig meget på mine erfaringer fra andre programmeringssprog (f.eks. kendskab til de mange begreber, osv), så det går forholdsvist hurtigt og smertefrit med at sætte sig ind i C++. :-)
#1
Følgende kode viser mere hvad der sker:
Følgende kode viser mere hvad der sker:
#include <iostream>
#include <vector>
using namespace std;
class P
{
protected:
int vp;
public:
P(int vp) { this->vp = vp; }
virtual void print() { cout << "P val: " << vp << " (@" << (int)this << ")" << endl; }
P(const P& o) { this->vp = o.vp; cout << "P copy: " << (int)&o << "->" << (int)this << endl; }
};
class C : public P
{
protected:
int vc;
public:
C(int vp, int vc) : P(vp) { this->vc = vc; }
virtual void print() { cout << "C val: " << vp << " " << vc << " (@" << (int)this << ")" << endl; }
C(const C& o) : P(o) { this->vc = o.vc; cout << "C copy: " << (int)&o << "->" << (int)this << endl; }
};
int main()
{
cout << "create P" << endl;
P op(123);
cout << "print P" << endl;
op.print();
cout << "create C" << endl;
C oc(456, 789);
cout << "print C" << endl;
oc.print();
vector<P> v;
cout << "save P in vector" << endl;
v.push_back(op);
cout << "save C in vector" << endl;
v.push_back(oc);
cout << "print vector" << endl;
v[0].print();
cout << "print vector" << endl;
v[1].print();
return 0;
}
Gå til top
Opret dig som bruger i dag
Det er gratis, og du binder dig ikke til noget.
Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.