Konstruktor wywolujacy metode

0

Witam

Jak powinien wygladac konstruktor i funkcja main() w ponizszym przykladzie?

Czy konstruktor moglby wywolywac metode Load()?

 
#include <conio.h>
#include <iostream>

class A
{
 private:
  int c;
  int* d; int* e;

 public:
  void Load(int &c, int* &d, int* &e)
  {cout<<"Podaj c"; cin>>c;
   d= new int[c];
   e= new int[c];
   cout<<Podaj d oraz e<<endl;
   for(int i=0; i<n; i++)
   {cin>>d[i];
    cin>>e[i]; 
   }
  }
}

int main()
{
 A a;
 int c;
 int* d; int* e;

 a.Load(c,d,e);

 for(int i=0; i<c; i++) cout<<d[i]<<", "<<e[i]<<endl;

 return 0;
 getche();
}
0

Normalnie:

A() {
  Load(); // lub this->Load();
}
0

funkcja Load przyjmuje argumenty int &c, int* &d, int* &e, czy zatem konstruktor też musi je przyjąć?

czy zatem traktować konstruktor jak funkcję?

1

rrany boskie. jeśli funkcja Load przyjmuje parametry, to musisz ją wywołać z tymi parametrami. możesz je wymyśleć wewnątrz konstruktora:

A() {
  Load(wszystkie,potrzebne,parametry);
}

albo jeśli chcesz je podawać z zewnątrz, zdefiniuj konstruktor z parametrami:

A(int &c, int* &d, int* &e)
{
  Load(c,d,e);
}
0

Dzieki, wszystko ladnie dziala. Na przyszlosc bede juz umial.

Jednakze pojawia sie kolejne pytanie - jaka musi byc postac konstruktora klasy B(ktora jest pochodna klasy A), tak, aby wykonywal funkcje MakeF()?

 
#include <conio.h>
#include <iostream>
 
class A
{
 private:
  int c;
  int* d; int* e;
 
 public:
  A(int &c, int* &d, int* &e)
  {Load(c, d, e);
   for(int i=0; i<c; i++) cout<<d[i]<<", "<<e[i]<<endl;
  }

  void Load(int &c, int* &d, int* &e)
  {cout<<"Podaj c"; cin>>c;
   d= new int[c];
   e= new int[c];
   cout<<Podaj d oraz e<<endl;
   for(int i=0; i<c; i++)
   {cin>>d[i];
    cin>>e[i]; 
   }
  }
  
  void MakeF(int &c, int* d, int* e, int* F)
  {F= new int[c];
   for(int i=0; i<c; i++) F[i]=d+e;
  }
};
 

class B : public A
{
 public:
  MakeG(int &c, int* &F, int* &G)
  {G= new int[c];
   for(int i=0; i<c; i++) G[i]=F[i];
  }
};

int main()
{int c;
 int* d; 
 int* e;

 A a(c, d, e);

 int* F;
 a.makeF(c, d, e, F);
 
 int* G;
 B b;
 b.makeG(c, F, G);

 for(int i=0; i<c; i++) cout<<G[i]<<endl;
 
 return 0;
 getche();
}

Przy okazji chcialbym zapytac o wyglad destruktora dla obu klas. Powinny byc wirtualne i bezargumentowe?

0
Ziomson007 napisał(a)

chcialbym zapytac o wyglad destruktora dla obu klas. Powinny byc wirtualne i bezargumentowe?
a widziałeś kiedyś destruktor z argumentami? Gdy dziedziczysz powinieneś zadeklarować w klasie bazowej destruktor jako wirtualny.

0

Błędów w tym kodzie jest jak kobiet w galerii, o formatowaniu kodu nie wspomnę.

void MakeF(int &c, int* d, int* e, int* F) // albo przy parametrach d i e dasz referencje...
  {F= new int[c];
   for(int i=0; i<c; i++) F[i]=d+e; // albo przy d i e wyłuskasz wartości poprzedzając je '*'
class B : public A
{
 public:
  MakeG(int &c, int* &F, int* &G) // jaki typ zwraca ta funkcja?
a.MakeF(c, d, e, F); // funkcja byla nazwana z duzej litery wiec musi tutaj tez byc z duzej, podobnie...
 
 int* G;
 B b;
 b.MakeG(c, F, G); // ...tutaj

Aż boję się odpalać ten program, bo z niego cieknie jak z mojego prysznica. Jak definiujesz obiekt za pomocą operatora new to tą zarezerwowaną pamięć należy zwolnić operatorem delete.

Nie wiem, co robi ten kod, bo się nie przyglądałem, ale jeśli klasa B jest pochodną klasy A, to jeżeli klasa A ma domyślny konstruktor, to tworzac obiekt klasy B konstruktora klasy A wykona się automatycznie.
Możesz też wywołać konstruktor jawnie w konstruktorze B().

class B : public A
{
public:
    B()
    {
        A();
    }
};
0

Przepraszam za bledy, funkcja oczywiscie nic nie zwraca, jest typu void.
Staram sie przerobic kod, aby byl obiektowy, i tworze jego model uproszczony do minimum w notatniku.
Na chwile obecna problem pojawia sie z chwila gdy pojawia sie dziedziczenie.
Chcialbym aby konstruktor klasy B wywolywal metode MakeG().

 
#include <conio.h>
#include <iostream>
 
class A
{
 private:
  int c;
  int* d; int* e;
 
 public:
  A(int &c, int* &d, int* &e)
  {Load(c, d, e);
   for(int i=0; i<c; i++) cout<<d[i]<<", "<<e[i]<<endl;
  }
  virtual ~A();

  void Load(int &c, int* &d, int* &e)
  {cout<<"Podaj c"; cin>>c;
   d= new int[c];
   e= new int[c];
   cout<<Podaj d oraz e<<endl;
   for(int i=0; i<c; i++)
   {cin>>d[i];
    cin>>e[i]; 
   }
  }
  
  void MakeF(int &c, int* d, int* e, int* F)
  {F= new int[c];
   for(int i=0; i<c; i++) F[i]=d+e;
  }
};
 

class B : public A
{
 public:
  B(int &c, int* &F, int* &G)
  {MakeG(c, F, G);
  }
  ~B(){}

  void MakeG(int &c, int* &F, int* &G)
  {G= new int[c];
   for(int i=0; i<c; i++) G[i]=F[i];
  }
};

int main()
{int c;
 int* d; 
 int* e;

 A a(c, d, e);

 int* F;
 a.MakeF(c, d, e, F);
 
 int* G;
 B b(c,F,G);

 for(int i=0; i<c; i++) cout<<G[i]<<endl;
 
 return 0;
 getche();
}
0

No to wywołuje, a jeśli chcesz wywołać jeszcze konstruktor klasy A, to robisz to tak:

  B(int &c, int* &F, int* &G)
    {
        A(c, F, G);
        MakeG(c, F, G);
    }

Ale w dalszym ciągu nie zwalniasz zarezerwowanej pamięci. A uruchamiając ten program parenaście razy, w zależności od zmiennych w SPACJA końcu zapełnisz pamięć komputera do tego stopnia, że nie będziesz mógł odpalić nawet sapera.

1

@MJay: Nie prawda, tak się nie odpala konstruktora klasy nadrzędnej, a przynajmniej nie w kontekście w jakim to rozumiesz. Jeżeli chcesz odpalić konkretny konstruktor klasy bazowej to musisz użyć do tego listy inicjalizacyjnej.
Tak jak Ty to robisz to tworzysz tymczasowy obiekt klasy A, który jest do niczego nie używany.

0

Panowie, to w koncu jak zadeklarowac ten konstruktor w klasie B aby wykonywal metode MakeG?

 

#include <conio.h>
#include <iostream>

using namespace std;

class A
{
private:
    int c;
    int* d; int* e;

public:
    A(int &c, int* &d, int* &e)
    {
        Load(c, d, e);
    }
    virtual ~A(){}

    void Load(int &c, int* &d, int* &e)
    {
        cout<<"Podaj c"<<endl;
        cin>>c;
        d = new int[c];
        e = new int[c];
        cout<<"Podaj d oraz e"<<endl;
        for(int i=0; i<c; i++)
        {
            cin>>d[i];
            cin>>e[i];
        }
    }
    void MakeF(int &c, int* d, int* e, int* F)
    {
        F= new int[c];
        for(int i=0; i<c; i++)
        {
            F[i]=d[i]+e[i];
        }
    }
};

class B : public A
{
public:
    B(int &c, int* &F, int* &G)
    {
        MakeG(c, F, G);
    }
    ~B(){}

    void MakeG(int &c, int* &F, int* &G)
    {
        G = new int[c];
        for(int i=0; i<c; i++)
        {
            G[i]=F[i];
        }
    }
}


int main()
{
    int c;
    int* d;
    int* e;

    A a(c, d, e);
    cout<<""<<endl;

    int* F;
    a.MakeF(c, d, e, F);

    B b(c, F, G);

    for(int i=0; i<c; i++)
    {
        cout<<G[i]<<endl;
    }

    system("pause");
    return 0;
    getche();
}
0

W klasie A konstruktor jest publiczny podczas dziedziczenia znajduje się on w klasie B. Takie wywołanie działa i destruktor odpala się dopiero przy zakończeniu programu. Nie widzę tutaj błędu

0

@MJay przestań regularnie ludzi w błąd wprowadzać. Przekonaj się doświadczalnie:

#include <iostream>
using namespace std;

class A {
public:
  A(int a, int b, int c)
  {
    cout << "konstruktor A, this:" << this << endl;
  }
  ~A()
  {
    cout << "destruktor A" << endl;
  }
};

class B {
public:
  B(int a, int b, int c) {
    cout << "konstruktor B, this:" << this << endl;
    A(a, b, c);
  }
  ~B() {
    cout << "destruktor B" << endl;
  }
};

int main() {
  B *b = new B(1, 2, 3);
  cout << "po utworzeniu B" << endl;
  delete b;
}

B jest tworzony na stercie aby różnica adresów pomiędzy obiektami (B i tymczasowym A na stosie) była wyraźnie widoczna. Wynik:

konstruktor B, this:0x3d3d90
konstruktor A, this:0x22ff1f
destruktor A
po utworzeniu B
destruktor B

gdyby było tak jak mówisz to this dla B i dla A byłby identyczny. Destruktor A leci w momencie opuszczenia konstruktora B. Zrób światu przysługę i zamiast "pomagać" sam się naucz podstaw.

0

@up Wydaje mi się, że byku_guzio ma rację. Czym bowiem ta sytuacja różni się od poniższego kodu?

#include <iostream>

struct Base {
    int i;
    Base() : i(0) { std::cerr << "Base()\n"; }
    Base(int n) : i(n) { std::cerr << "Base(" << n << ")\n"; }
    virtual ~Base() { std::cerr << "~Base(" << i << ")\n"; }
    void foo() { std::cerr << i << '\n'; }
};

struct A : Base {
    A(int n) {
        Base(66);
        std::cerr << "A(" << n << ")\n"; }
    ~A() { std::cerr << "~A(" << i << ")\n"; }
};

struct B : Base {
    B(int n) : Base(n) { 
        std::cerr << "B(" << n << ")\n"; }
    ~B() { std::cerr << "~B(" << i << ")\n"; }
};

int main() {
    using namespace std;
    A a(3);
    B b(6);
    
    return 0;
}

Szczególnie dobrze to widać, jeżeli usuniemy konstruktor domyślny z Base - ten kod się w ogóle nie skompiluje, bo konstruktor A spróbuje wywołać Base() (bo w liście inicjalizacyjnej nie ma innego wywołania konstruktora).

1 użytkowników online, w tym zalogowanych: 0, gości: 1