Forum: C++: Hjälp med en övning, någon?

Forum huvudsida -> Programmering -> C++: Hjälp med en övning, någon?

Sidor: 1 2

Till botten

olle 01:31 - 24:e Juli 2006 | Post #1
Medlem
Inlägg: 57


Skicka PM
Hej igen!

Håller på och gör en övning från en gamma kurs jag läste förut. Men jag tror att några av funktioner jag definerat i "group.cpp" är fel. När jag kompilerar min projekt med "make" så får jag inget fel. Men när exekverar filen så kommer det upp en ruta som det ska. Men efter det så krashar programmet. Jag får meddelandet

"Avbruten (SIGABRT)"

Verkar som det har med minneshanteringen och göra eller något som ni kanske kan lista ut?

Här har jag en bild på själva uppgiften om ni har lust och kolla.

http://img228.imageshack.us/img228/6748/groups1oz8.jpg
http://img157.imageshack.us/img157/6586/groups2qj0.jpg


Här kommer källkoden:
ps: Ni kan ej kompilera det pga att den behöver lite saker och är ett projekt ( make etc )

Sen tar jag inte med alla includerings filer som ej berör uppgiften

shape.h
  1. #ifndef SHAPE_H
  2. #define SHAPE_H
  3. #include <qwidget.h>
  4. #include "types.h"
  5. /* An abstract base class of shapes */
  6. class Shape {
  7. public:
  8. Shape(QWidget *aWidget,const char *n,QColor c,Point p);
  9. void getName(char *str) const;
  10. QColor getColor() const;
  11. void setColor(QColor c);
  12. Point getPos() const;
  13. void moveTo(Point p);
  14. void move(int dx,int dy);
  15. // pure virtual functions
  16. virtual void draw() const = 0; // only implemented
  17. virtual void erase() const = 0; // in subclasses
  18. virtual Shape* clone() const = 0;
  19. protected:
  20. char myName[100];
  21. QColor myColor;
  22. Point myPos;
  23. QWidget *theWidget;
  24. };
  25. #endif



rect.h
  1. #ifndef RECT_H
  2. #define RECT_H
  3. #include "shape.h"
  4. #include <qwidget.h>
  5. class Rectangle : public Shape {
  6. public:
  7. Rectangle(QWidget *aWidget,const char *name,QColor c,Point p,int w,int h);
  8. void draw() const;
  9. void erase() const;
  10. Rectangle* clone()const;
  11. int getWidth() const;
  12. int getHeight() const;
  13. void setSize(int width,int height);
  14. private:
  15. int myWidth,myHeight;
  16. void drawRect(QColor c) const;
  17. };
  18. #endif



ellipse.h
  1. #ifndef ELLIPSE_H
  2. #define ELLIPSE_H
  3. #include "shape.h"
  4. #include <qwidget.h>
  5. class Ellipse : public Shape {
  6. public:
  7. Ellipse(QWidget *aWidget,const char *name,QColor c,Point p,int xr,int yr);
  8. void draw() const;
  9. void erase() const;
  10. Ellipse* clone() const;
  11. int getXradius() const;
  12. int getYradius() const;
  13. void setRadius(int xradius,int yradius);
  14. private:
  15. int myXradius, myYradius;
  16. void drawEllipse(QColor c) const;
  17. };
  18. #endif



circle.h
  1. #ifndef CIRCLE_H
  2. #define CIRCLE_H
  3. #include <qwidget.h>
  4. #include "ellipse.h"
  5. class Circle : public Ellipse{
  6. public:
  7. Circle( QWidget *aWidget,const char *name,QColor c,Point p,int radius );
  8. int getRadius( );
  9. void setRadius( int radius );
  10. void draw()const;
  11. void erase()const;
  12. Circle* clone()const;
  13. private:
  14. int myRadius;
  15. void drawCircle(QColor c)const;
  16. };
  17. #endif


square.h
  1. #ifndef SQUARE_H
  2. #define SQUARE_H
  3. #include "rect.h"
  4. #include <qwidget.h>
  5. class Square : public Rectangle{
  6. public:
  7. Square( QWidget *aWidget,const char *n,QColor c,Point p,int side );
  8. int getSize();
  9. void setSize(int size);
  10. void draw()const;
  11. void erase()const;
  12. Square* clone()const;
  13. private:
  14. int mySide;
  15. void drawSquare(QColor c)const;
  16. };
  17. #endif


group.h
  1. #ifndef GROUP_H
  2. #define GROUP_H
  3. #include <vector.h>
  4. #include "shape.h"
  5. #include <qwidget.h>
  6. class Group : public Shape {
  7. public:
  8. Group( QWidget *aWidget);
  9. ~Group();
  10. Group( const Group & );
  11. Group* clone()const;
  12. // void move();
  13. void draw()const;
  14. void erase()const;
  15. Group& operator+= ( Shape& sp );
  16. private:
  17. Vector<Shape*> TheShapeList;
  18. };
  19. #endif


Detta är vad jag behöver hjälp med.
group.cpp
  1. #include "group.h"
  2. #include <qpainter.h>
  3. Group::Group( QWidget *aWidget) : Shape(theWidget,myName,myColor,myPos) { }
  4. Group::~Group() {} // Hur gör man?
  5. Group::Group( const Group & x) : Shape(x) {
  6. for ( int i = 0; i < TheShapeList.size();i++)
  7. TheShapeList[i] = x.TheShapeList[i];
  8. }
  9. Group* Group::clone()const {
  10. Group *gp = new Group(theWidget);
  11. return gp;
  12. }
  13. void Group::draw()const {
  14. for (int i = 0;i < TheShapeList.size();i++)
  15. TheShapeList[i]->draw();
  16. }
  17. void Group::erase()const {
  18. for (int i = 0;i < TheShapeList.size();i++)
  19. TheShapeList[i]->erase();
  20. }
  21. Group& Group::operator+= ( Shape& sp ){
  22. // Ser ej bra ut?? Om vector = 0 --> i+1 ?
  23. int i = TheShapeList.size();
  24. TheShapeList[i+1] = sp.clone();
  25. return *this;
  26. }



grouptest.cpp
  1. // demonstration of shape groups
  2. #include <qapplication.h> // Qt
  3. #include <picturedisplay.h>
  4. #include <iostream>
  5. #include "shape.h"
  6. #include "rect.h"
  7. #include "ellipse.h"
  8. #include "square.h"
  9. #include "circle.h"
  10. #include "group.h"
  11. using namespace std;
  12. void paintMain( int argc, char **argv, PictureDisplay *pd ) {
  13. Ellipse e(pd,"An ellipse",Qt::yellow,Point(100,100),50,30);
  14. Square s(pd,"A square",Qt::green,Point(300,200),70);
  15. Circle c(pd,"A circle",Qt::blue,Point(300,200),120);
  16. Rectangle r(pd,"A rectangle",Qt::magenta,Point(100,100),200,50);
  17. Group g(pd);
  18. pd->askMore();
  19. g.draw();
  20. (((g += e) += s) += c) += r;
  21. g.draw();
  22. pd->askMore();
  23. /*
  24. g.move(100,100);
  25. pd->askMore();
  26. g.move(-200,0);
  27. pd->askMore();
  28. g.move(0,-150);
  29. pd->askMore();
  30. g.move(100,0);
  31. pd->askMore( "Beware of the clones!" );
  32. g.erase();
  33. pd->askMore();
  34. Group *gptr = g.clone();
  35. for ( int i = 0; i < 5; i++ ) {
  36. gptr->move(-10,10);
  37. g.draw();
  38. pd->askMore();
  39. }
  40. g.erase();
  41. pd->askMore( "Test absolute movement of group" );
  42. Group *gptr2 = gptr->clone();
  43. for ( int i = 0; i < 5; i++ ) {
  44. gptr2->moveTo(Point(100+10*i,100+10*i));
  45. pd->askMore();
  46. }
  47. gptr->erase();
  48. gptr2->erase();
  49. pd->askMore( "Test a group of groups" );
  50. // A group consisting of two subgroups of ...
  51. Group gg(pd), *tmp = g.clone();
  52. tmp->move(10,-10); // so its position differs from g's
  53. tmp->erase();
  54. (gg += g) += *tmp; // make a hiearchical group
  55. for ( int i = 0; i < 10; i++ ) {
  56. gg.move(20,20);
  57. pd->askMore();
  58. }
  59. */
  60. }
  61. int main( int argc, char **argv ) {
  62. QApplication a( argc, argv );
  63. PictureDisplay pd( argc, argv, paintMain ); // create picture display
  64. a.setMainWidget( &pd ); // set main widget
  65. pd.show(); // show it
  66. return a.exec(); // start event loop
  67. }


Alla andra klasser såsom shape, circle, rectangle, square etc fungerar utmärkt om jag tex skapar vanligt utan att använda group objekt. Min clone funktion fungerar i alla klasser förutom kanske i Group. Tror man måste göra om den lite grann. Sen är jag nästan osäker på alla funktioner jag gjort i Group. Destruktorn vet jag ej hur man skulle gå tillväga. Man ska tydligen göra den virtual i Shape klassen och definera den i resternade subklasserna.
move funktionen har jag skippat så länge tills jag får allt annat och fungera.

Tar med en av andra klasser ifall någon ville se.
Alla andra ser nästan likadana ut.

  1. #include <qpainter.h>
  2. #include "rect.h"
  3. // Constructor
  4. Rectangle::Rectangle(QWidget *aWidget,const char *n,QColor c,Point p,int w,int h)
  5. : Shape(aWidget,n,c,p), myWidth(w), myHeight(h) { }
  6. int Rectangle::getWidth() const { return myWidth; }
  7. int Rectangle::getHeight() const { return myHeight; }
  8. void Rectangle::setSize(int width,int height) {
  9. erase();
  10. myWidth = width;
  11. myHeight = height;
  12. draw();
  13. }
  14. void Rectangle::drawRect(QColor c) const {
  15. // these are QT routines!
  16. QPainter myPainter( theWidget );
  17. QPen pen( c, 2 );
  18. myPainter.setPen( pen );
  19. myPainter.drawRect(myPos.x,myPos.y,myWidth,myHeight);
  20. QFont f( "courier", 12, QFont::Bold );
  21. myPainter.setFont( f );
  22. myPainter.drawText(myPos.x,myPos.y,myWidth,myHeight,Qt::AlignCenter, myName);
  23. }
  24. void Rectangle::draw() const { drawRect(myColor); }
  25. void Rectangle::erase() const {
  26. QPainter myPainter(theWidget);
  27. drawRect(myPainter.backgroundColor());
  28. }
  29. Rectangle* Rectangle::clone()const {
  30. Rectangle *rp = new Rectangle(theWidget,myName,myColor,myPos,myWidth,myHeight);
  31. return rp;
  32. }


Hehe detta blev rätt så mycket. Hoppas jag ej är till stor besvär..De enda som är fel ligger i group.cpp.

Tack i förhand

Ha de gött

ps: Som sagt får inget kompilerings fel. Utan blir fel i själva exekveringen. Tror minneshantering. operator+= och koperingskonstruktorn är nog fel.

-------------------------
Ingen signatur!

Senast redigerad 01:47 - 24:e Juli 2006


Independence 07:36 - 24:e Juli 2006 | Post #2
Administratör
Inlägg: 1800


Skicka PM
Man brukar få "Segfault" när det är fel på minneshanteringen tror jag. "Sigabrt" låter som "signal abort", dvs att någon sa till programmet att stänga av sig. Vet inte riktigt vad det betyder dock Smiley Kan vara så att OSet stängde av programmet för att det drog för mycket minne kanske?

Edit:
TheShapeList[i+1]
Borde väl fungera antar jag, lägger till ett element sist i listan. Som jag kommer ihåg att man brukar göra är dock TheShapeList.append(sp.clone());
eller nåt i den stilen. Kan iofs vara att jag blandar ihop det med något annat dock Smiley

-------------------------

Vi är riddarna som säger fiskbulle!



Senast redigerad 07:41 - 24:e Juli 2006


Nissebosselasse 08:18 - 24:e Juli 2006 | Post #3
Medlem
Inlägg: 490


Skicka PM
Har bara ögnat igenom det jättesnabbt, men ska du inte göra en push_back istället för TheShapeList[i+1], eftersom det är en std::vector? Den enda containerklass som jag vet som stödjer sådant, är std::map.

Ang. SIGABRT: mjukvarusignaler (som finns i signal.h) genereras av funktionen raise, och det finns olika signaler beroende på vilken typ av signal man vill åtstadkomma (SIGINT, SIGTERM, etc.).
Just SIGABRT kommer från att någon antagligen har anropat funktionen abort; eftersom du använder ett tredjepartsbibliotek (QT), så är väl risken att det är något däri som spökar (såvida det inte är din vektor som spökar med minnet).

Läs mer om SIGABRT här: http://msdn2.microsoft.com/en-us/library/k089yyh0.aspx

-------------------------
http://pushingcows.se
Gula Nallen



olle 11:35 - 24:e Juli 2006 | Post #4
Medlem
Inlägg: 57


Skicka PM
Testade och skriva

  1.  
  2.  
  3. Group& Group::operator+= ( Shape& sp ){
  4. TheShapeList.push_back(sp); // testade *sp feldärmed
  5. return *this;
  6. }


Men fick felmdeddelade:

group.cpp: In member function `Group& Group::operator+=(Shape&)':
group.cpp:59: no matching function for call to `Vector<Shape*>::push_back(Shape&)'
vector.h:99: candidates are: void Vector<Object>::push_back(const Object&) [with Object=Shape*]

Vad jag vet så ska QT fungera utmärk. Pga att jag har gjort denna övning tidigare ( 2år sen ). Det som är fel är själva funktiionen operator +=.

Tar jag bort denna rad så får jag ej SIGABRT.
( grouptest.cpp )
(((g += e) += s) += c) += r;


Sen kanske mer funktioner i group.cpp är fel.

Begriper inte varför den gör abort på själva processen.

Tack för att ni försöker hjälpa mig.



-------------------------
Ingen signatur!



Nissebosselasse 12:50 - 24:e Juli 2006 | Post #5
Medlem
Inlägg: 490


Skicka PM
Du kan inte göra så eftersom argumentet till operator+= är en referens (Shape &), medan vektorn innehåller pekare (Shape *).
Borde fungera:
  1.  
  2. Group& Group::operator+= ( Shape& sp ){
  3. // Antar att sp.close() returnerar en pekare?
  4. TheShapeList.push_back(sp.clone());
  5. return *this;
  6. }


Alternativt borde det här också fungera, d.v.s., ta ut adressen till referensen:
  1.  
  2. Group& Group::operator+= ( Shape& sp ){
  3. TheShapeList.push_back (&sp);
  4. return *this;
  5. }

Jag gjorde ett litet test med det sista alternativet, och det fungerade bra. Men nu kanske detta inte är det enda problemet i programmet...

Tänkte på raden (((g += e) += s) += c) += r;, det är kanske något av resultaten (d.v.s. av de överlagrade operator+=) som returnerar en NULL-pekare.

-------------------------
http://pushingcows.se
Gula Nallen



olle 13:41 - 24:e Juli 2006 | Post #6
Medlem
Inlägg: 57


Skicka PM
Tack för hjälpen. Nu fungerar raden

(((g += e) += s) += c) += r;

Nästa steg jag testade var och se om jag kunde göra en kopia av g till en annan Group objekt:

  1. // demonstration of shape groups
  2. #include <qapplication.h> // Qt
  3. #include <picturedisplay.h> // added by UH
  4. #include <iostream>
  5. #include "shape.h"
  6. #include "rect.h"
  7. #include "ellipse.h"
  8. #include "square.h"
  9. #include "circle.h"
  10. #include "group.h"
  11. using namespace std;
  12. void paintMain( int argc, char **argv, PictureDisplay *pd ) {
  13. Ellipse e(pd,"An ellipse",Qt::yellow,Point(100,100),50,30);
  14. Square s(pd,"A square",Qt::green,Point(300,200),70);
  15. Circle c(pd,"A circle",Qt::blue,Point(300,200),120);
  16. Rectangle r(pd,"A rectangle",Qt::magenta,Point(100,100),200,50);
  17. Group g(pd);
  18. pd->askMore();
  19. g.draw();
  20. (((g += e) += s) += c) += r;
  21. g.draw();
  22. Group *m = g.clone(); // gör en klone
  23. pd->askMore();
  24. g.erase();
  25. pd->askMore();
  26. m->draw();
  27. pd->askMore();


Men när jag kompilerar och kör så ritar den inte upp nåt. Verkar som Group::clone() funktionen inte är riktigt rätt.
I uppgifter står det att man ska utnyttja kopieringskonstruktorn i definitionen av Group::clone().
Tror jag ej använder det riktigt. För kopieringskonstruktorn anropas endast när man skapar en ny objekt och gör själva tilldelning. Tycker jag gjort rätt eller?

  1. Group* Group::clone()const {
  2. Group *gp = new Group(theWidget);
  3. return gp;
  4. }


Borde man inte använda "this" någonstans här med clone() funktionen för respektiv Objekt som redan är definerad beoende på vilken typ det är??

Men nu kom jag på att man ska göra på detta sätt:
Men detta är fel oxo. Pga att den gör en clone av själva gp.

  1. Group* Group::clone()const {
  2. Group *gp = new Group(theWidget);
  3. gp->clone();
  4. return gp;
  5. }


Kör jag programmet så får jag "Segmenteringsfel". Så nu kan man säga att det är minneshanteringen.

Måste nog fixa destruktorn. För jag har inte deallokerat någonstans och vet ej hur definitionen ska se ut i just den funktionen. Man ska tydligen ha virtual ~Shape = 0. Sen definera det i subklasserna.

Tack till Nissebosselasse och Independence som hjälper till.

Hoppas jag ej är till besvär som sagt


-------------------------
Ingen signatur!

Senast redigerad 14:37 - 24:e Juli 2006


olle 14:58 - 24:e Juli 2006 | Post #7
Medlem
Inlägg: 57


Skicka PM
Står att man ska använda kopykonstruktorn när man gör Group::clone(). Men hur fixar man så att den gör en kopia av den objekt som anroper clone() funktionen? Man borde använda "this" isåfall ?

Sen kanske jag måste använda push_back i definitionen av kopykonstruktorn?



  1. Group::Group( const Group & x) : Shape(x) { //Aggregat relation mellan Group och Shape: utkärning sker
  2. // djup kopiering
  3. for ( int i = 0; i < TheShapeList.size();i++)
  4. TheShapeList[i] = x.TheShapeList[i];
  5. }


I funktionen Group::clone() så undrar jag vad man ska skriva i själva argumentet när man försöker använda kopykonstruktorn



  1. Group* Group::clone()const {
  2. Group g(?);
  3. // Sen tänkte jag göra en for loop som går igenom alla vector i just den objekt som anropade clone() och push_backa den till den nya objekt g.
  4. // Men vet ej hur man ska åstakomma detta, kanske med hjälp av "this"?


Uppskattas all hjälp

-------------------------
Ingen signatur!

Senast redigerad 15:01 - 24:e Juli 2006


Nissebosselasse 16:17 - 24:e Juli 2006 | Post #8
Medlem
Inlägg: 490


Skicka PM
Först och främst om clone-funktionen:
  1.  
  2. Group* Group::clone() const {
  3. Group *gp = new Group(theWidget);
  4. gp->clone();
  5. return gp;
  6. }

När avslutas funktionen? Aldrig! Du skapar ett nytt objekt, anropar dess clone-funktion, som i sin tur skapar ett nytt objekt och därefter anropar sin clone-funktion, som skapar ett nytt objekt och därefter anropar... I evighet.

Jag får återkomma med det andra - du kanske rent av kommer på en lösning under tiden! Smiley

-------------------------
http://pushingcows.se
Gula Nallen



olle 17:48 - 24:e Juli 2006 | Post #9
Medlem
Inlägg: 57


Skicka PM
Hehe nu när du säger det så är det logiskt att man anropar samma funktion som en loop. Försöker lista ut vad man ska göra när man skapar en Group g(?) med vilken argument i Group::clone() funktionen.

Sen när det gäller kopieringskontruktorn så har jag nu precis felsökt genom att skriva:

  1. #include <qapplication.h> // Qt
  2. #include <picturedisplay.h> // added by UH
  3. #include <iostream>
  4. #include "shape.h"
  5. #include "rect.h"
  6. #include "ellipse.h"
  7. #include "square.h"
  8. #include "circle.h"
  9. #include "group.h"
  10. using namespace std;
  11. void paintMain( int argc, char **argv, PictureDisplay *pd ) {
  12. Ellipse e(pd,"An ellipse",Qt::yellow,Point(100,100),50,30);
  13. Square s(pd,"A square",Qt::green,Point(300,200),70);
  14. Circle c(pd,"A circle",Qt::blue,Point(300,200),120);
  15. Rectangle r(pd,"A rectangle",Qt::magenta,Point(100,100),200,50);
  16. Group g(pd);
  17. pd->askMore();
  18. g.draw();
  19. (((g += e) += s) += c) += r;
  20. g.draw();
  21. Group w(g); // Använder kopieringskontruktorn för test
  22. pd->askMore();
  23. g.erase();
  24. pd->askMore();
  25. w.draw(); // ritar upp inget
  26. pd->askMore();


Tydligen fel i kopieringskonstruktorn. Ska försöka testa med push_back() istället.

Verkar som jag inte begriper nåt heh, får inte till det o fungera med push_back. Säkert nåt fel jag gör.

-------------------------
Ingen signatur!

Senast redigerad 18:15 - 24:e Juli 2006


Nissebosselasse 19:06 - 24:e Juli 2006 | Post #10
Medlem
Inlägg: 490


Skicka PM
Så här gjorde jag med min kopieringskonstruktor:
  1. Group::Group (Group &g)
  2. {
  3. // Med push_back
  4. //*
  5. std::vector<Shape *>::iterator it = g.beginIterator ();
  6. m_shapelist.clear ();
  7. for (; it != g.endIterator(); ++it) {
  8. m_shapelist.push_back (*it);
  9. }
  10. //*/
  11. // Med std::copy istället
  12. /*
  13. m_shapelist.clear ();
  14. std::copy (g.beginIterator(), g.endIterator(), std::back_inserter(m_shapelist));
  15. //*/
  16. }

Eller, det är två varianter egentligen. Den första använder sig av push_back, och den andre använder en av STL-bibliotekets algoritmer (std::copy), samt std::back_inserter, som allokerar minne automatiskt för varje nytt element som ska sättas in (annars hade man fått reservera minne först innan anropet till std::copy, så att det garanterat fick plats).

EDIT: ska kanske visa Group.h också:
  1.  
  2. #ifndef JT_GROUP_H
  3. #define JT_GROUP_H
  4.  
  5. #include "Shape.h"
  6. #include <vector>
  7.  
  8. class Group {
  9. public:
  10. Group () {}
  11. Group (Group &);
  12. ~Group () {}
  13.  
  14. Group &operator+= (Shape &s);
  15.  
  16. void displayAll ();
  17.  
  18. std::vector<Shape *>::iterator beginIterator () { return m_shapelist.begin(); }
  19. std::vector<Shape *>::iterator endIterator () { return m_shapelist.end(); }
  20.  
  21. inline size_t Size () const { return m_shapelist.size(); }
  22.  
  23. private:
  24. std::vector<Shape *> m_shapelist;
  25. };
  26.  
  27. #endif


-------------------------
http://pushingcows.se
Gula Nallen

Senast redigerad 19:14 - 24:e Juli 2006


olle 19:57 - 24:e Juli 2006 | Post #11
Medlem
Inlägg: 57


Skicka PM
Lägger jag in din kod i group.h och group.cpp
så får jag

In file included from ../../sources/grouptest.cpp:12:
../../sources/include/group.h:24: syntax error before `::' token
../../sources/include/group.h:25: ISO C++ forbids defining types within return
type
../../sources/include/group.h:25: syntax error before `::' token
make: *** [binaries/grouptest.o] Error 1

  1.  
  2. Group::Group( const Group & x) : Shape(x) {//Aggregat relation basklass=subklass-group: utkärning
  3.  
  4. // Sen gör vi en kopia av group attributen oxo
  5.  
  6. vector<Shape *>::iterator it = x.beginIterator ();
  7.  
  8. TheShapeList.clear();
  9. for (; it != x.endIterator(); ++it) {
  10. TheShapeList.push_back (*it);
  11. }



  1.  
  2.  
  3. #ifndef GROUP_H
  4. #define GROUP_H
  5. #include <vector>
  6. #include "shape.h"
  7. #include <qwidget.h>
  8.  
  9.  
  10. class Group : public Shape {
  11. public:
  12. Group( QWidget *aWidget); // Konstruktorn
  13. ~Group(); // Destruktorn
  14. Group( const Group & ); // kopieringskonstruktorn
  15. Group* clone()const;
  16. // void move();
  17. void draw()const;
  18. void erase()const;
  19. Group& operator+= ( Shape& sp );
  20. vector<Shape *>::iterator beginIterator () { return TheShapeList.begin(); }
  21. vector<Shape *>::iterator endIterator () { return TheShapeList.end(); }
  22. private:
  23. Vector<Shape*> TheShapeList;
  24. };
  25.  
  26. #endif
  27.  


Innan har jag använd egen vector.h fil som man får med i själva övningen. Den ser ut såhär.

  1.  
  2. #ifndef _VECTOR_H
  3. #define _VECTOR_H
  4.  
  5. // Vector class interface: support bounds-checked arrays
  6.  
  7. //
  8. // Object: must have zero-parameter constructor and operator=
  9. // CONSTRUCTION: with (a) an integer size only
  10.  
  11. //
  12.  
  13. // ******************PUBLIC OPERATIONS*********************
  14.  
  15. // = --> Copying assignment
  16.  
  17. // [ ] --> Indexing with bounds check
  18.  
  19. // bool empty( ) --> Return true if Vector empty, false ow
  20. // int size( ) --> Return # elements in Vector
  21. // int capacity( ) --> Return capacity of vector
  22. // void resize( int newSize ) --> Change bounds of Vector
  23. // void reserve( int newCapacity ) --> Change Vector capacity
  24. // void push_back( Object x ) --> Add x at end of Vector
  25.  
  26. #include <stdlib.h>
  27. template <class Object>
  28.  
  29. class Vector {
  30. public:
  31. explicit Vector( int initSize = 0 )
  32. : theSize( initSize ), theCapacity( initSize + SPARE_CAPACITY )
  33. { objects = new Object[ theCapacity ]; }
  34. Vector( const Vector & rhs ) : objects( NULL ) { operator=( rhs ); }
  35. ~Vector( ) { delete [ ] objects; }
  36.  
  37. bool empty( ) const { return size( ) == 0; }
  38. int size( ) const { return theSize; }
  39. int capacity( ) const { return theCapacity; }
  40.  
  41. Object & operator[]( int index ) {
  42. if( index < 0 || index >= size( ) )
  43. throw "Vector::[]: Index out of bounds" ;
  44. return objects[ index ];
  45. }
  46.  
  47. const Object & operator[]( int index ) const {
  48. if( index < 0 || index >= size( ) )
  49. throw "Vector::[]: Index out of bounds" ;
  50. return objects[ index ];
  51. }
  52. const Vector & operator = ( const Vector & rhs );
  53. void resize( int newSize );
  54. void reserve( int newCapacity );
  55. void push_back( const Object & x );
  56. enum { SPARE_CAPACITY = 16 };
  57. private:
  58. int theSize;
  59. int theCapacity;
  60. Object *objects;
  61. };
  62.  
  63. template <class Object>
  64. const Vector<Object> & Vector<Object>::operator=( const Vector<Object> & rhs ) {
  65. if( this != &rhs ) {
  66. delete [ ] objects;
  67. theSize = rhs.size( );
  68. theCapacity = rhs.theCapacity;
  69.  
  70. objects = new Object[ capacity( ) ];
  71. for( int k = 0; k < size( ); k++ )
  72. objects[ k ] = rhs.objects[ k ];
  73. }
  74. return *this;
  75. }
  76.  
  77. template <class Object>
  78. void Vector<Object>::resize( int newSize ) {
  79. if( newSize > theCapacity )
  80. reserve( newSize * 2 );
  81. theSize = newSize;
  82. }
  83. template <class Object>
  84. void Vector<Object>::reserve( int newCapacity ) {
  85. Object *oldArray = objects;
  86. int numToCopy = newCapacity < theSize ? newCapacity : theSize;
  87. newCapacity += SPARE_CAPACITY;
  88. objects = new Object[ newCapacity ];
  89. for( int k = 0; k < numToCopy; k++ )
  90. objects[ k ] = oldArray[ k ];
  91. theSize = numToCopy;
  92. theCapacity = newCapacity;
  93. delete [ ] oldArray;
  94. }
  95.  
  96. 1template <class Object>
  97.  
  98. void Vector<Object>::push_back( const Object & x ) {
  99. if( theSize == theCapacity )
  100. reserve( 2 * theCapacity + 1 );
  101. objects[ theSize++ ] = x;
  102. }
  103. #endif
  104.  


Vad är de för fel nu då?

-------------------------
Ingen signatur!



Nissebosselasse 20:03 - 24:e Juli 2006 | Post #12
Medlem
Inlägg: 490


Skicka PM
Alltså, först och främst: det var aldrig tänkt att du skulle klippa & klistra in min kod i ditt projekt rakt av; jag visade bara min kopieringskonstruktur så att du skulle få lite idéer hur du kunde implementera det själv i din kod.

-------------------------
http://pushingcows.se
Gula Nallen



olle 20:07 - 24:e Juli 2006 | Post #13
Medlem
Inlägg: 57


Skicka PM
aha ok.

Grejen e den att jag använder en egen vector.h fil.
Den jag har har inte funktioner som begin() och end(). Men ska försöka fixa på något annat sätt och få inspiration från din kod.

Måste man includera något speciellt när man använder iterator?

Tror den klagar på nåt pga det, är ej säkert

-------------------------
Ingen signatur!



Nissebosselasse 20:13 - 24:e Juli 2006 | Post #14
Medlem
Inlägg: 490


Skicka PM
Så länge du använder STL-biblioteket (Standard Template Library), så följer sådana saker automatiskt med.

Mitt tips: skippa egna varianter på STL-grejerna (som Vector i ditt fall), och kör på STL:s egna.

Jag skapade en ny tråd ("Gratis böcker om..."), ladda ner dom två böckerna om C++ ("Thinking in C++ (vol 1 och vol 2)"). Det är jävligt bra böcker som beskriver STL och alla dess nyttiga grejer.

-------------------------
http://pushingcows.se
Gula Nallen



olle 20:23 - 24:e Juli 2006 | Post #15
Medlem
Inlägg: 57


Skicka PM
Ska nog använda STL bibliotek som du säger. Men som jag har förstått så är denna en av STL.
#include<vector>

Men varför klagar kompilator om att typen vector ej finns när jag har includerat den??

group.h:27: 'vector' is used as a type, but is not
defined as a type.
make: *** [binaries/grouptest.o] Error 1


Hoppas jag ej är för jobbig nu hehe


edit:

Den klagar inte på vector längre. Så det är lungt Smiley

tack igen för allt

-------------------------
Ingen signatur!

Senast redigerad 20:43 - 24:e Juli 2006


Nissebosselasse 21:34 - 24:e Juli 2006 | Post #16
Medlem
Inlägg: 490


Skicka PM
STL:s vector-klass (eller template, som det är) ligger i namnrymden ("namespace") std. Och vad jag kan utläsa från t.ex. group.h, så använder du varken ett using-direktiv, eller prefixet std::, varför kompilatorn inte "vet" vad en vector är.

Du måste t.ex. göra (bland annat):
  1.  
  2. // Innan stod det följande:
  3. // Vector<Shape*> TheShapeList;
  4.  
  5. // ...men ska vara med STL (om inte "using namespace std;" används):
  6. std::vector<Shape*> TheShapeList;
  7.  


EDIT: såg att det löste sig, va bra! Och oroa dig inte för att posta frågor, det är ju det forumet är till för Smiley

-------------------------
http://pushingcows.se
Gula Nallen



olle 22:20 - 24:e Juli 2006 | Post #17
Medlem
Inlägg: 57


Skicka PM
Tack för svaret igen Smiley

Lika bra jag ställer en till nu när jag är igång hehe

Börjar få lite panik när jag ser att jag ej förstår vad kompilator säger:

../../sources/group.cpp: In copy constructor `Group::Group(const Group&)':
../../sources/group.cpp:41: passing `const Group' as `this' argument of `
__gnu_cxx::__normal_iterator<Shape**, std::vector<Shape*,
std::allocator<Shape*> > > Group::beginIterator()' discards qualifiers
../../sources/group.cpp:44: passing `const Group' as `this' argument of `
__gnu_cxx::__normal_iterator<Shape**, std::vector<Shape*,
std::allocator<Shape*> > > Group::endIterator()' discards qualifiers
make: *** [binaries/group.o] Error 1


Har försökt utgå från din kod för att göra kopykonstruktorn
Pga att jag ej kommer på en annan lösning.

  1.  
  2. Group::Group( const Group & x) : Shape(x) {//Aggregat relation basklass=subklass-group: utkärning
  3.  
  4. std::vector<Shape *>::iterator it = x.beginIterator();
  5.  
  6. TheShapeList.clear();
  7. for (; it != x.endIterator(); ++it) {
  8. TheShapeList.push_back (*it);



  1.  
  2. class Group : public Shape {
  3. public:
  4. Group( QWidget *aWidget); // Konstruktorn
  5. ~Group(); // Destruktorn
  6. Group( const Group & ); // kopieringskonstruktorn
  7. Group* clone()const;
  8. // void move();
  9. void draw()const;
  10. void erase()const;
  11. Group& operator+= ( Shape& sp );
  12. std::vector<Shape*>::iterator beginIterator();
  13. std::vector<Shape*>::iterator endIterator();
  14. private:
  15. std::vector<Shape*> TheShapeList;
  16. };


Vad är det som är felet här?

uppskattas verkligen med all hjälp


-------------------------
Ingen signatur!



Nissebosselasse 23:18 - 24:e Juli 2006 | Post #18
Medlem
Inlägg: 490


Skicka PM
Jag upptäckte också det felet innan när jag först gjorde koden, och kom fram till att det ligger i Group (const Group &);.

Som du ser i min förra post (eller, förr-förra, eller vad det nu blir), så uteslöt jag const, eftersom kompilatorn klagade på att det inte gick, men så fort jag tog bort const, så fungerade det.

,,ndringen jag gjorde nu var att dels lägga till const igen (som du har det), och dels i kopieringskonstruktorn göra mig av med const:en (brrrr-tsch! Smiley ):
group.cpp
  1.  
  2. // Nu skickas g som en referens, som är 'const'
  3. Group::Group (const Group &g)
  4. {
  5. // "Kasta om" till en ny referens (g2),
  6. // och ta samtidigt bort const-delen
  7. Group &g2 = const_cast<Group&>(g);
  8.  
  9. // Samma kod, men vi använder g2 istället,
  10. // som ju inte har 'const'
  11. std::vector<Shape *>::iterator it = g2.beginIterator ();
  12.  
  13. m_shapelist.clear ();
  14. for (; it != g2.endIterator(); ++it) {
  15. m_shapelist.push_back (*it);
  16. }
  17. }


Känns lite dumt att man inte kan förklara varför - men, men, man kan ju inte veta allt!

-------------------------
http://pushingcows.se
Gula Nallen



olle 10:54 - 25:e Juli 2006 | Post #19
Medlem
Inlägg: 57


Skicka PM
Vad hade jag gjort utan dig. ...terigen så fixade du problemet Smiley

Nu fungerar kopykonstruktorn, tackar.

Har gjort nu Group::clone() funktionen där jag använt mig av kopykonstruktorn enligt övningen.

  1.  
  2. Group* Group::clone()const {
  3. Group g(theWidget);
  4. Group *gp = new Group(g); // Använder kopykonstruktorn
  5.  
  6. return gp;
  7. }


Tycker detta ser korrekt ut? Eller så är jag helt fel ute.

Såhär ser group_test.cpp ut. Kanske klonar jag på felsätt när jag ska testa det.

  1.  
  2. using namespace std;
  3.  
  4. void paintMain( int argc, char **argv, PictureDisplay *pd ) {
  5. Ellipse e(pd,"An ellipse",Qt::yellow,Point(100,100),50,30);
  6. Square s(pd,"A square",Qt::green,Point(300,200),70);
  7. Circle c(pd,"A circle",Qt::blue,Point(300,200),120);
  8. Rectangle r(pd,"A rectangle",Qt::magenta,Point(100,100),200,50);
  9.  
  10. Group g(pd);
  11. pd->askMore();
  12.  
  13. g.draw();
  14. (((g += e) += s) += c) += r;
  15. g.draw();
  16. Group *m = g.clone(); // klonar g och retunerar pekare
  17. pd->askMore();
  18. g.erase();
  19. pd->askMore();
  20. m->draw();
  21. pd->askMore();



Tack för all hjälp som sagt

-------------------------
Ingen signatur!



Nissebosselasse 12:18 - 25:e Juli 2006 | Post #20
Medlem
Inlägg: 490


Skicka PM
Inget jag testat, men jag funderade på:
  1. Group* Group::clone() const {
  2. Group *gp = new Group(*this);
  3. return gp;
  4. }


En viktig regel dock att komma ihåg: allt du new:ar, ska tas bort med delete, annars får du minnesläckor.

EDIT: testade det nu, och det fungerade.

-------------------------
http://pushingcows.se
Gula Nallen

Senast redigerad 12:29 - 25:e Juli 2006


olle 13:03 - 25:e Juli 2006 | Post #21
Medlem
Inlägg: 57


Skicka PM
Nu fungerar Group::clone() oxo Smiley Tackar

Har nu oxo gjort funktionen Group::move() där man tydligen skulle göra shape:s move till virtual så att Shape pekaren ska kunna använda Group::move() ifall typen är av Group i vectorn.

  1.  
  2. void Group::move(int dx,int dy){
  3. for(int i=0; i < TheShapeList.size();i++)
  4. (*this).TheShapeList[i]->move(dx,dy);
  5. }


Denna fungerar utmärkt. Men som vanligt min första version så tog jag ej med (*this) och det blev fel. Så man kan lungt säga att jag har problem när man använder "this" eller inte.
Vet vad det är men andå har jag problem med det.

this är väl den objekt som har anropat funktionen eller?

Men varför räcker det inte och köra utan this när man andå använder TheShapeList attributen till den objekt som ska flyttas i funktionen Group::move() ?

Tror det är nåt som jag ej förstår

Men nu har du iallfall hjälpt mig med denna övning som är nästan färdig. Bara Destruktorn kvar. Ska se om jag kan lösa den innan jag frågar dig igen Smiley

Tack hemskt mycket för all hjälp




-------------------------
Ingen signatur!



Nissebosselasse 14:27 - 25:e Juli 2006 | Post #22
Medlem
Inlägg: 490


Skicka PM
this är en pekare till instansen av klassen. Och som med alla pekare, så gäller även här att en asterisk (*) före pekaren returnerar själva objektet.
Här kan du läsa mer om this-pekaren: http://msdn2.microsoft.com/en-us/library/y0dddwwd.aspx



-------------------------
http://pushingcows.se
Gula Nallen



olle 16:34 - 25:e Juli 2006 | Post #23
Medlem
Inlägg: 57


Skicka PM
Men när dessa tre rader är samma sak,

  1.  
  2. void Date::setMonth( int mn )
  3. {
  4. month = mn; // These three statements
  5. this->month = mn; // are equivalent
  6. (*this).month = mn;
  7. }


varför kan jag då inte skriva

  1.  
  2. void Group::move(int dx,int dy){
  3. for(int i=0; i < TheShapeList.size();i++)
  4. TheShapeList[i]->move(dx,dy);
  5. }


För att
  1.  
  2. // samma betydelse
  3. TheShapeList[i]->move(dx,dy);
  4. (*this).TheShapeList[i]->move(dx,dy);
  5. this->.TheShapeList[i]->move(dx,dy);


Det är just detta som jag ej förstår. För man har ju tillgång till attributen i just den objet som anropar den funktionen.

Hoppas du förstår hur jag menar och tänker.


-------------------------
Ingen signatur!



Nissebosselasse 17:02 - 25:e Juli 2006 | Post #24
Medlem
Inlägg: 490


Skicka PM
Vad får du för felmeddelande?

-------------------------
http://pushingcows.se
Gula Nallen



olle 17:31 - 25:e Juli 2006 | Post #25
Medlem
Inlägg: 57


Skicka PM
Tror jag måste gå och vila mig lite grann. Verkar som jag suttit framför dator alldeles förlänge Smiley

När jag hade använt utan (*this) i funktionen group::move()
så hade jag i grouptest.cpp gjort lite annorlunda så att jag ej såg resultatet. Nu kommer jag ej ihåg exakt hur det var. Då kunde jag kompilerade utan att få fel. Men såg att den ej rörde sig.

Men nu visar det sig att den fungerar hehe. Måste varit fel i grouptest.cpp som sagt.

Så slutsatsen är att man använder (*this) när man verkligen behöver göra det som tex i clone() funktionen?

Brukar man oxo alltid använda det i operator += eller = etc?
eller är det fall till fall?




-------------------------
Ingen signatur!



Sidor: 1 2

Forum huvudsida -> Programmering -> C++: Hjälp med en övning, någon?
Atom feed

Du får inte posta i den här tråden | Till toppen