Avatar billede javanic Nybegynder
16. april 2004 - 14:26 Der er 19 kommentarer og
1 løsning

indsæt objekt i array

Et rigtigt begynder-spørgsmål, der reelt kun går på hvordan man indsætter et objekt i et array.

Jeg har et par klasser - Rektangel og Cirkel, der begge bedarver fra en abstrakt Figur klasse. Derudover har jeg lavet en Tabel-klasse, der reelt kun udgør et enkelt array af typen Firgur, tab[8][8].
Nu vil jeg så gerne (fra min main) kunne kalde Tabel-klassens insert-metode, og indsætte henholdsvis Cirkel- og Rektangel-objekter i min tabel.

min tabel er erklæret med (tabel.h):
Figur tab[8][8];


Jeg havde tænkt lidt på at lave en min insert alá (tabel.cpp):
void Tabel::insert(int x, int y, Figur &f)
{
    this->tab[x][y] = &f;
}


og så kalde den med f.eks.:
Figur *f = new Cirkel();
int i = 0, j = 0;
insert(i,j, f) ;

....hvad gør jeg ?
Avatar billede arne_v Ekspert
16. april 2004 - 14:55 #1
Hvis du retter til:

void Tabel::insert(int x, int y, Figur *f)
{
    this->tab[x][y] = *f;
}

så tror jeg at det compiler.
Avatar billede javanic Nybegynder
16. april 2004 - 15:09 #2
Det har jeg også prøvet, men så får jeg en error C2664:
"Tabel::insert' : cannot convert parameter 3 from 'Figur **__w64  ' to 'Figur *"

...og som den newbie jeg er til c++, troede jeg at jeg skulle igang med at lave en operator= overload !
Avatar billede arne_v Ekspert
16. april 2004 - 15:16 #3
Du har ikke ændret:

insert(i,j, f) ;

til:

insert(i,j, &f) ;

?
Avatar billede arne_v Ekspert
16. april 2004 - 15:17 #4
Du skal formentlig have lavet en operator=.

Men C++ laver en default.

Imidelrtid duer den ike hvis du f.eks. har dynamisk allokeret memory i klasserne.
Avatar billede javanic Nybegynder
16. april 2004 - 15:26 #5
hmm.... vent nu lige lidt. Grunden til at den går kold, skyldes nok at jeg kalder insert() fra en anden metode i Tabel-klassen, hvor jeg parameter-overfører et array.

Jeg har nemlig lavet fill() metode, der automatisk skal indsætte henholdsvis Cirkel- og Rektangel-objekter i tabellen.

void Tabel::fillTabel(Figur *figurArray[2])
{   
    int x;

    //    srand(seed): Sets a random starting point.
    srand( (unsigned)time(NULL) );

    // (tabellens y-akse):
    for(int i=0; i<8; i++)
    {   
        // (tabellens x-akse):
        for(int j=0; j<8; j++)
        {
            rand();
            x = x = 0 + rand() % 2;
            this->insert(i,j, *figurArray[x]) ;
        }
    }
}


...og så havde jeg tænkt mig at kalde den fra main. Noget i stil med:

Figur *f1 = new Cirkel();   
Figur *f2 = new Rektangel();
Tabel *table = new Tabel();
   
Figur *figurArray[2] = { f1, f2};
table->fillTabel(figurArray);

..Hvodan genbruger jeg egentlig en pointer,...så jeg slipper for at oprette 2 seperate?
Avatar billede javanic Nybegynder
16. april 2004 - 15:27 #6
...håber at du kan følge mig ? :o)
Avatar billede arne_v Ekspert
16. april 2004 - 16:03 #7
Umiddelbart ser det ud til at:

this->insert(i,j, *figurArray[x]) ;

skal ændres til:

this->insert(i,j, figurArray[x]) ;
Avatar billede arne_v Ekspert
16. april 2004 - 16:03 #8
Du kan altid genbruge en pointer, men du skal værer færdig med at bruge det den
peger på først.
Avatar billede javanic Nybegynder
16. april 2004 - 16:23 #9
ok,...umiddelbart tager den det nu - thanks ;o)

Lige et sidste (par) spørgsmål:
Hvordan får jeg typecastet mine "Figur" pointere, når jeg løber min tabel igennem, så jeg kan få kaldt Cirkel-klassens 'getAreal()' metode på Cirkel-objekterne og Rektangel-klassens getAreal() på mine Rektangel-objekter...

F.eks. ved:

for(int i=0; i<8; i++)
{
    cout << "\n" << i << "\t";
    for(int j=0; j<8; j++)
    {
        cout << (this->tab[i][j])..getAreal() << "\t";
    }
    cout << "\n";
}

...og har C++ ikke en metode, hvorpå jeg kan finde frem til hvilken type objekt et element er - lidt alá Javas "get.Class().getName()" ?
Avatar billede arne_v Ekspert
16. april 2004 - 16:34 #10
Nej - du kan ikke i standard C++ på runtime finde typen af et objekt.

Men men men.

Du kan bare kalde:

this->tab[i][j].getAreal()

helt ligesom i Java.

Hvis (!) Figur indeholder:

virtual int getAreal() = 0;

og Cirkel og Rektangel klaserne indeholder:

virtual int getAreal()
{
  return ...;
}
Avatar billede arne_v Ekspert
16. april 2004 - 16:34 #11
Og et svar
Avatar billede javanic Nybegynder
16. april 2004 - 16:45 #12
...takker mange gange for din hjælp, Arne.

Dog fik jeg en lille "error C2259: 'Figur' : cannot instantiate abstract class"
hvor den brokker sig over "Figur tab[8][8];" i min Tabel-klasse...
Avatar billede arne_v Ekspert
16. april 2004 - 16:49 #13
Ah ja - vi fik jo lige lavet Figur abstrakt.

virtual int getAreal()
{
  return -1;
}
Avatar billede javanic Nybegynder
16. april 2004 - 17:06 #14
det hjalp jp... takker igen!!

Men man har altså i C++ IKKE mulighed for at identificere af hvilken type et objekt er, i runtime - har jeg forstået dig ret !

Du behøver ikke uddybe,...bare så jeg ikke går på jagt efter noget der ikke findes ;o)

og takker da lige endnu engang (ydmygt) for din hjælp....
Avatar billede arne_v Ekspert
16. april 2004 - 17:50 #15
Hvis du skal søge så skal du søge efter RTTI.

Men det er ikke ligesom Java. Og jeg mener at det er helt eller delvist
compiler specifikt.

Stort set ingen bruger det.
Avatar billede arne_v Ekspert
16. april 2004 - 17:51 #16
Det kan næsten altid anbefales i C++ aldrig at lade objekter indeholde
andre objekter men kun pointere til andre objekter.

(og så gør det heller ikke noget at Figur bliver abstrakt)
Avatar billede bertelbrander Novice
16. april 2004 - 23:52 #17
Et eksempel på brug af type info kunne være:

#include <iostream>
#include <typeinfo>

using namespace std;

class MyClass
{
public:
  int x;
};

int main()
{
  int i;
  cout << typeid(MyClass).name() << endl;
  cout << typeid(i).name() << endl;
}

Bemærk dog at output vil være forskelligt fra kompiler til kompiler.
Jeg har mest set det brugt til debug.
Det kan ikke anbefales at bruge det til:

if(typeid(SomePointer).name() == "WhateverClass")
  SomePointer->X();
else
  SomePointer->Y();

RTTI bruges også til dynamic_cast, hvis det er enablet, derved kan man lave en typesikker cast.
Avatar billede arne_v Ekspert
17. april 2004 - 13:00 #18
Jeg har leget lidt videre med Bertels eksempel:

#include <iostream>
#include <string>
#include <typeinfo>

using namespace std;

class MyClass
{
};

class MySubClass : public MyClass
{
};

int main()
{
  int i = 123;
  string s = "abc";
  MyClass *mc = new MyClass();
  MySubClass *msc = new MySubClass();
  MyClass *mcmsc = new MySubClass();
  cout << typeid(i).name() << endl;
  cout << typeid(s).name() << endl;
  cout << typeid(mc).name() << endl;
  cout << typeid(msc).name() << endl;
  cout << typeid(mcmsc).name() << endl;
  cout << typeid(*mc).name() << endl;
  cout << typeid(*msc).name() << endl;
  cout << typeid(*mcmsc).name() << endl;
  return 0;
}

GCC 3.1/mingw output:

i
Ss
P7MyClass
P10MySubClass
P7MyClass
7MyClass
10MySubClass
7MyClass

MS VC++ 6:

int
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char>>
class MyClass *
class MySubClass *
class MyClass *
class MyClass
class MySubClass
class MyClass

BCB 5.5:

int
std::basic_string<char,std::char_traits<char>,std::allocator<char> >
MyClass *
MySubClass *
MyClass *
MyClass
MySubClass
MyClass
Avatar billede arne_v Ekspert
17. april 2004 - 13:12 #19
Lidt forskelligt. Og den sidste er iøvrigt "forkert" i forhold hvad en
Java programmør forventer.
Avatar billede bertelbrander Novice
17. april 2004 - 14:13 #20
Jeg havde også forventet at den ville være klog nok til at fortælle at mcmsc i virkeligheden peger på en MySubClass, det andet er med til at gøre det endnu mere ubrugeligt i praksis.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester