CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - każda klasa w oddzielnym pliku...

każda klasa w oddzielnym pliku...

dział ogólny

Re: każda klasa w oddzielnym pliku...

Nowy postprzez polymorphism » poniedziałek, 30 października 2017, 20:46

std::unique_ptr użyłem z nawyku. We współczesnym C++ można praktycznie do zera zredukować użycie new i delete (i generalnie ręczne zarządzanie pamięcią). Możesz użyć std::auto_ptr.

czy deklaracje funkcji muszę ubierać w konwencje wywołania: __fastcall ?

Nie musisz. __fastcall jest (chyba) wymagane dla metod, które mają być podpinane pod zdarzenia.


Zmień środowisko na nowsze...
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez Arnold_S » poniedziałek, 30 października 2017, 22:38

Dlaczego nie używam bardziej współczesnego środowiska?
Otóż dobrym wyjściem byłoby MS Visual Studio, bo można aktualnie i za darmo. Niestety (jak kiedyś wspomniałeś) nie ma tam WYSYWIG-a dla C++. Czyli musiałbym tworzyć własnoręcznie konstrukcję okna i wszelakich elementów.
Inny darmowy to CodeBlocks, który mam i używam do pisania aplikacji konsolowych (jest mega wygodny). Przy apkach okienkowych trzeba robić wszystko ręcznie - patrz wyżej.

Dlatego toczę ten kamień pod górę w Embarcadero Rad Studio XE2 bo lwią robotę wykonuję poprzez przeciągnięcie elementów na formę i korzystanie z funkcji...etc.
Nigdy nie umieszczałem w tym XE2 klas abstrakcyjnych i pochodnych. Mówiąc wprost nie mam doświadczenia i gubię się gdy kompilator rzyga megatony błędów...więc przeglądam docs.embarcadero.com pod kątem błędów i próbuję sam je eliminować. Pojawiają się schody gdy nie widzę błędu, a program usilnie twierdzi, że jest...wtedy przychodzę tutaj - do doświadczonych programistów. Dla mnie jesteście kopalnią wiedzy i patrząc po wielkiej kolekcji tutoriali chyba każdy z Was kiedyś używał BCB v6 lub XE2,XE4. Zanim powstał c++14,11 i jeszcze wcześniej, ludzie jakoś radzili sobie z takimi błahymi problemami jak moje nawet w BCB v6. To jest powód dla którego trzymam się tego nieszczęsnego środowiska.

/edit
Następny projekt zacznę budować w CodeBlocks przy ewentualnej pomocy wxWidgets lub QtCreator. Mam trochę dość tego borlanda, wiem też, że wiele w tym mojej niewiedzy.
Te śmieszne klasy "zwierze" i "kot" to tylko przykład, który zrobiłem na potrzeby przedstawienia problemu. Tak naprawdę chciałem skończyć to co zacząłem (większy projekt) by nie robić tego od nowa w innym środowisku. Mam fajnie poukładaną formę, a na niej około 50 pól Edit, kilkanaście Memo, całą masę Labelów i inne. Wszystko dopieszczone. Klasę abstrakcyjną i cztery potomne pisałem w notepad++. Bardzo wygodne dla mnie narzędzie ponieważ daje ogromne możliwości edycji masowej (wierszy, kolumn), ułatwia pracę bo można dostosować kolor tła oraz tekstu zależnie od składni. Tak więc powstało kilka większych klas w odrębnych plikach. Stąd moje natarczywe pytania i upartość dla tego nieszczęsnego Rad Studio XE2. Gdybym wkleił zawartość tych dużych klas to jestem pewny, że żadnemu z Was nie chciałoby się tego czytać.
Po to stworzyłem zwierze.h i kot.h+kot.cpp. W internetach szukałem sporo o tym jak zaimplementować własne klasy (abstrakcyjne i pochodne), w oddzielnych plikach, w tym środowisku (krok po kroku). Serio niczego konkretnego nie znalazłem.
Avatar użytkownika
Arnold_S
Homos antropiczny
Homos antropiczny
 
Posty: 58
Dołączył(a): niedziela, 12 czerwca 2016, 23:22
Podziękował : 15
Otrzymał podziękowań: 0
System operacyjny: Win7 64b
Kompilator: C++ Builder 6, Rad Studio XE2
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez polymorphism » wtorek, 31 października 2017, 11:48

Inny darmowy to CodeBlocks, (...) Przy apkach okienkowych trzeba robić wszystko ręcznie - patrz wyżej.

To IDE ma rozszerzenie wxSmith dla biblioteki wxWidgets, więc nie jest tak źle. Generalnie rzecz biorąc wszystkie te designery dla Qt czy wxWidgets są dość podobne, jeśli chodzi o wygodę, i nieco różnią się od tego z c++ buildera. Początki mogą być trudne, ale warto...

Dlatego toczę ten kamień pod górę w Embarcadero Rad Studio XE2 bo lwią robotę wykonuję poprzez przeciągnięcie elementów na formę i korzystanie z funkcji...etc.
Nigdy nie umieszczałem w tym XE2 klas abstrakcyjnych i pochodnych. Mówiąc wprost nie mam doświadczenia i gubię się gdy kompilator rzyga megatony błędów...

To jest IMO główna "wada" tego środowiska, że ludzie piszą w nim przez dłuższy czas, a w efekcie nie znają często podstawowych rzeczy z C++, mają spore braki, które wyłażą, kiedy trzeba zrobić coś więcej niż kliknięcie komponentu w designerze.

Klasę abstrakcyjną i cztery potomne pisałem w notepad++. Bardzo wygodne dla mnie narzędzie ponieważ daje ogromne możliwości edycji masowej (wierszy, kolumn), ułatwia pracę bo można dostosować kolor tła oraz tekstu zależnie od składni.

Sprawdź VSCode - ma większe możliwości edycji wieloliniowej/multikursorowej. W połączeniu z clangiem całkiem niezły intellisense i sprawdzanie składni w locie.

W internetach szukałem sporo o tym jak zaimplementować własne klasy (abstrakcyjne i pochodne), w oddzielnych plikach, w tym środowisku (krok po kroku). Serio niczego konkretnego nie znalazłem.

"W tym środowisku" robi się to tak samo, jak w innych IDE dla C++.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez Arnold_S » środa, 1 listopada 2017, 01:20

Czy chciałbyś mi pomóc?
Próbowałem z tym auto_ptr. Efekt jest ten sam co wcześniej.
Efekt jest mniej więcej taki, że wskaźnik polimorficzny jakby nie widzi funkcji z klasy pochodnej mimo, że są identyczne pod względem argumentów i zwracanych typów. W konsekwencji chce korzystać z obiektów prywatnych...których nie ma bo te zadeklarowałem tylko w klasie pochodnej.
Mam wrażenie, że sam mechanizm moich klas jest właściwy, korzystam z klasy abstrakcyjnej właściwie, tylko albo źle to włączam do projektu, albo nie w tym miejscu co trzeba. Posiadasz może to RadStudio XE2? Poprostu wkleiłbym CI treść tych dwóch małych klas: zwierze i kot, a Ty sprawdziłbyś u siebie. Mogę też wysłać Ci cały testowy projekcik. Wówczas zobaczysz co gdzie dodałem i dlaczego źle.
Ewentualnie jeśli masz doświadczenie z tym XE2 to może mógłbyś mi pomóc właściwie umieścić te moje klasy, tak aby działały. Czytałem dokumentację o klasach abstrakcyjnych z tego Embarcadero i nic nie piszą tam magicznego. Wszystko wydaje mi się klarowne i zgodne dotychczasową wiedzą. Mimo wszystko działać nie chce.
Avatar użytkownika
Arnold_S
Homos antropiczny
Homos antropiczny
 
Posty: 58
Dołączył(a): niedziela, 12 czerwca 2016, 23:22
Podziękował : 15
Otrzymał podziękowań: 0
System operacyjny: Win7 64b
Kompilator: C++ Builder 6, Rad Studio XE2
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez polymorphism » środa, 1 listopada 2017, 12:02

Posiadasz może to RadStudio XE2?

Nie korzystam C++ Buildera od kilkunastu lat (i wracać nie zamierzam). Pokaż kod. Do analizy nie potrzebne mi jest RadStudio czy inne IDE.

Efekt jest mniej więcej taki, że wskaźnik polimorficzny jakby nie widzi funkcji z klasy pochodnej mimo, że są identyczne pod względem argumentów i zwracanych typów.

A czy są wirtualne (bo to jest kluczowe w polimorfizmie)?
C++ Reference - opis wszystkich klas STL-a i funkcji C.

Za ten post autor polymorphism otrzymał podziękowanie od:
Arnold_S
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez Arnold_S » środa, 1 listopada 2017, 12:28

Zerknij na to. Najpierw wkleję Unit1.h i Unit1.cpp projektu w XE2.

Unit.h
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include "zwierze.h"      // tutaj wstawiłem moje klasy
#include "kot.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TMemo *Memo1;
        TMemo *Memo2;
        TMemo *Memo3;
        TButton *Button1;
        void __fastcall Button1Click(TObject *Sender);
private:        // User declarations
public:         // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


Unit1.cpp
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <iostream>
#include <memory>  //dla auto_ptr
#include "Unit1.h"
#include <ctime>          // dla time();
#include <cstdlib>   // dla srand();

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
   srand(static_cast<unsigned int>(time(0)));
}
//---------------------------------------------------------------------------
        //kot dachowiec;
        //zwierze *wsk = &dachowiec;

        //test auto_ptr
        std::auto_ptr <zwierze> wsk(new kot);
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        wsk->losuj_uszy();
        wsk->losuj_oczy();
        wsk->losuj_futro();
        UnicodeString temp1 = wsk->Wyjmijstr((*wsk).uszy);
        UnicodeString temp2 = wsk->Wyjmijstr(oczy);
        UnicodeString temp3 = wsk->Wyjmijstr(futro);

        Memo1->Lines->Add(temp1);
        Memo2->Lines->Add(temp2);
        Memo3->Lines->Add(temp3);
}
//---------------------------------------------------------------------------



Teraz moje klasy:
Abstrakcyjna "zwierze.h"

KOD cpp:     UKRYJ  
#ifndef ZWIERZE_H
#define ZWIERZE_H

#include <cstdlib>  //rand();
#include <string>


using namespace std;

class zwierze
{
public:
zwierze();
virtual ~zwierze();

enum rodzaj_kostki {K6=6, K10=10, K100=100};
unsigned short int rzut_kostka(rodzaj_kostki k);

virtual void losuj_uszy(void) = 0;
virtual void losuj_oczy(void) = 0;
virtual void losuj_futro(void) = 0;

virtual UnicodeString Wyjmijstr(const string &cos) = 0;

private:
rodzaj_kostki kostka;
};

///////////////////////////////////////////////
zwierze::zwierze() {}
zwierze::~zwierze(){}

unsigned short int zwierze::rzut_kostka(rodzaj_kostki k)
{
        kostka = k;
        return (1+(rand()%kostka));
}

#endif


kot.h
KOD cpp:     UKRYJ  
#ifndef KOT_H
#define KOT_H

//#include "zwierze.h"
#include <string>

using namespace std;

class kot : public zwierze
{
private:
string  uszy;
string oczy;
string futro;
rodzaj_kostki kostka;

public:
kot();
~kot();

//enum rodzaj_kostki {K6, K10, K100};
//unsigned short int rzut_kostka(rodzaj_kostki k);

void losuj_uszy(void);
void losuj_oczy(void);
void losuj_futro(void);

UnicodeString Wyjmijstr(const string &cos);

};

#endif


kot.cpp
KOD cpp:     UKRYJ  
#include <string>
#include "kot.h"

using namespace std;

kot::kot()
{
        uszy = "nie wylosowano";
        oczy = "nie wylosowano";
        futro = "nie wylosowano";
}

kot::~kot() {}

void kot::losuj_uszy()
{
        unsigned short int x = kot::rzut_kostka(K6);
        if(x <= 3)      { uszy = "długie"; }
        else            { uszy = "krótkie"; }
}

void kot::losuj_oczy(void)
{
        unsigned short int x = kot::rzut_kostka(K10);
        if(x <= 3)                      { oczy = "czerwone"; }
        if(x > 3 && x <= 6)     { oczy = "szare"; }
        if(x > 6)                       { oczy = "niebieskie"; }
}

void kot::losuj_futro(void)
{
        unsigned short int x = kot::rzut_kostka(K100);
        if(x <= 33)                             { futro = "w czarne paski"; }
        if(x > 33 && x <= 66)   { futro = "w plamki"; }
        if(x > 66)                              { futro = "kot bez futra"; }   
}

UnicodeString kot::Wyjmijstr(const string &cos)
{
        UnicodeString wynik = cos.c_str();
        return wynik;
}
Avatar użytkownika
Arnold_S
Homos antropiczny
Homos antropiczny
 
Posty: 58
Dołączył(a): niedziela, 12 czerwca 2016, 23:22
Podziękował : 15
Otrzymał podziękowań: 0
System operacyjny: Win7 64b
Kompilator: C++ Builder 6, Rad Studio XE2
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez polymorphism » środa, 1 listopada 2017, 14:49

KOD cpp:     UKRYJ  
wsk->Wyjmijstr((*wsk).uszy);

Nie możesz tak zrobić, uszy nie są częścią klasy zwierze, a Ty próbujesz się do nich dobrać.

Żeby to działało, musiałbyś zrobić to tak:
KOD cpp:     UKRYJ  
kot * p = dynamic_cast<kot*>(wsk.get());

UnicodeString temp1 = wsk->Wyjmijstr(kot->uszy); //uszy powinny być publiczne;  tu widać bezsens użycia `Wyjmijstr`

Nie sądzę, aby o to Ci chodziło.

KOD cpp:     UKRYJ  
class zwierze
{
        ...
        virtual void losuj_uszy(void) = 0;
        virtual void losuj_oczy(void) = 0;
        virtual void losuj_futro(void) = 0;
};

Jeśli dałeś te metody do klasy bazowej, to dlaczego nie zrobisz też metod getEars(), getEyes(), getFur()? W zasadzie do zwierze możesz przenieść także pola uszy, oczy i futro. Bo jeśli są w tej klasie metody losujące i pobierające wartości tych pól, to dlaczego nie mogą znaleźć się w niej także same pola? Tylko co jeśli zwierzę będzie rybą (która nie ma futra), albo meduzą (brak futra i uszu)?

Te pytania mają skłonić Cię do zastanowienia się nad hierarchią dziedziczenia i nad tym, co w danej klasie powinno się znaleźć, bo według mnie nie do końca wiesz, co chcesz zrobić.

Na razie tyle...
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez Arnold_S » środa, 1 listopada 2017, 21:08

Nie możesz tak zrobić, uszy nie są częścią klasy zwierze, a Ty próbujesz się do nich dobrać.

Chorobcia zapomniałem to usunąć. Był późny wieczór i sprawdzałem "co się stanie gdy". Wiem o tym, to wskaźnik, który pokazuje na klasę "zwierze", a w niej nie zadeklarowałem składników prywatnych z trzech powodów:
1. Chcę aby klasa zwierze była tylko abstrakcyjna. W sumie chciałbym dzięki wskaźnikowi jej typu używać funkcji wirtualnych we wszystkich klasach potomnych.
2. Z tego co kiedyś czytałem, to prywatnych składników się nie dziedziczy z klasy abstrakcyjnej (tylko publiczne)...czy mam rację?
3. Nigdy nie powstanie obiekt klasy zwierze wiec ostatecznie nie są do niczego potrzebne.

Jeśli dałeś te metody do klasy bazowej, to dlaczego nie zrobisz też metod getEars(), getEyes(), getFur()?

Liczne przykłady, które czytałem w internecie pokazują taką praktykę. Ja z niej zrezygnowałem dlatego, że chciałem aby była jedna metoda do odczytywania wartości z pól prywatnych typu string. Dlatego nazwałem ją "wyjmijstring". Jeśli zechciałbym stworzyć 48 pól tego typu to przy pomocy jednej funkcji mógłbym je odczytywać i przekazywać poza klasę, np.: do obiektu UnicodeString temp1. Taki był mój zamysł tworzenia tej metody. Gdy pojawi się potrzeba stworzenia 19 pól typu float, to stworzyłbym czysto wirtualną metodę "wyjmijfloat" i utworzyłbym ją w klasie kot.

Te pytania mają skłonić Cię do zastanowienia się nad hierarchią dziedziczenia i nad tym, co w danej klasie powinno się znaleźć, bo według mnie nie do końca wiesz, co chcesz zrobić.

Tak faktycznie, wygląda to trochę chaotycznie. Jak już wspomniałem wyżej, stworzyłem te dwie klasy i ich przykładowe(mega prymitywne) pola tylko po to aby zobaczyć mechanizm współpracy klas abstrakcyjnych z klasami z nich dziedziczącymi. Zobaczyć jak polimorficzny wskaźnik uruchamia metody wirtualne w klasach dziedziczących od abstrakcyjnej. Czy to działa w tym XE2 i czego się spodziewać.
Chciałbym ten mechanizm wykorzystać w większym projekcie i na potrzeby treningu utworzyłem klasy: zwierze i kot. Doskonale zdaję sobie sprawę z konsekwencji dołączenia do tej hierarchii klas: ryba czy krokodyl...bo to też są zwierzęta. Mają zupełnie inne cechy. Zwierze i kot nie ulegną rozwojowi w najbliższej przyszłości ani też hierarchia nie ulegnie większemu rozwojowi. Przy pomocy tych dwóch klas chcę zobaczyć na własne oczy jak działa polimorfizm...na takim bardzo ubogim przykładzie.

Ogólnie wiem jak wygląda ten mechanizm:
1. tworzę klasę abstrakcyjną zwierze, jej metody czysto wirtualne oraz publiczne metody na potrzebę dziedziczenia dla klasy kot.
2. tworzę klasę kot i deklaruję i definiuję virtualne metody oraz deklaruję/definiuję pola prywatne i metody, które wyjmą z nich dane poza klasę - patrz "wyjmijstring()"
3. gdy klasy są gotowe to:
- tworzę wskaźnik polimorficzny na klasę abstrakcyjną "zwierze":
KOD cpp:     UKRYJ  
zwierze * wskaz;


- tworzę obiekt klasy "kot":
KOD cpp:     UKRYJ  
kot dachowiec;


- ustawiam wskaźnik i mogę korzystać z dobrodziejstw wskaźnika polimorficznego:
KOD cpp:     UKRYJ  
wskaz = &dachowiec;
wskaz->losuj_uszy();
wskaz->losuj_futro();


- teraz chcę wyjąć to co wylosowałem:
KOD cpp:     UKRYJ  
UnicodeString temp = wskaz->wyjmijstring(dachowiec.uszy)


...No i to mi nie działa.
Gdy stworzę (tak zupełnie dla przykładu) następnego futrzaka, np.: pies. Będzie on miał ten sam zestaw pól i w pies.h zadeklaruję: class pies : public zwierze, to chcę ponownie użyć:
KOD cpp:     UKRYJ  
pies burek;
wskaz = &burek;
UnicodeString temp = wskaz->wyjmijstring(burek.uszy)



Dziękuję Ci za cierpliwość wiem, że możesz mi pomóc bo nawet Twój nick na forum za tym przemawia. 8-)
Jutro muszę wyjechać na kilka dni i nie będę mógł korzystać z pryw. komputera. Odsapnij ode mnie :D
Avatar użytkownika
Arnold_S
Homos antropiczny
Homos antropiczny
 
Posty: 58
Dołączył(a): niedziela, 12 czerwca 2016, 23:22
Podziękował : 15
Otrzymał podziękowań: 0
System operacyjny: Win7 64b
Kompilator: C++ Builder 6, Rad Studio XE2
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez polymorphism » środa, 1 listopada 2017, 21:56

Ja z niej zrezygnowałem dlatego, że chciałem aby była jedna metoda do odczytywania wartości z pól prywatnych typu string.

No to Ci przecież pokazałem, jak to można zrobić na przykładzie z metodami getTabSize() i getTab(). Nie rozumiem, dlaczego brniesz w tę, niezrozumiałą dla mnie, metodę Wyjmijstr().


Przykład z getTabSize() i getTab() ma jedną wadę - nie wiadomo, jakie cechy opisuje zwracana tablica. Dlatego tak jest sensowniej:
KOD cpp:     UKRYJ  
class animal
{
public:
        typedef std::pair<const char*, const char*> trait_type;

        virtual size_t getTraitsCount() const = 0;
        virtual trait_type getTrait(size_t i) const = 0;

        virtual ~animal() {}
};


class cat: public animal
{
public:
        size_t getTraitsCount() const { return 3; }
        trait_type getTrait(size_t i) const { return m_traits[ i]; }

        cat()
        {
                m_traits[0] = trait_type("oczy", "czerwone");
                m_traits[1] = trait_type("uszy", "długie");
                m_traits[2] = trait_type("futro", "w czarne paski");
        }
private:
        trait_type m_traits[3];
};



class dog: public animal
{
public:
        size_t getTraitsCount() const { return 3; }
        trait_type getTrait(size_t i) const { return m_traits[ i]; }

        dog()
        {
                m_traits[0] = trait_type("oczy", "czarne");
                m_traits[1] = trait_type("uszy", "krótkie");
                m_traits[2] = trait_type("futro", "brązowe");
        }
private:
        trait_type m_traits[3];
};


int main()
{
        cat c;
        dog d;


        animal* tab[] = { &c, &d };

        for(size_t j = 0; j < sizeof(tab) / sizeof(void*) ; ++j )
        {
                for(size_t i = 0; i < tab[j]->getTraitsCount(); ++i)
                {
                        animal::trait_type t = tab[j]->getTrait(i);

                        std::cout << t.first << ": " << t.second << '\n';
                }

                std::cout << '\n';
        }

        return 0;
}

Przeanalizuj to i wyciągnij wnioski.



..No i to mi nie działa.

uszy są prywatne, nie masz dostępu do tego pola z zewnątrz. Zrób to pole publiczne albo dorób publiczny getter (w poprzednim poście był drobny błąd).
C++ Reference - opis wszystkich klas STL-a i funkcji C.

Za ten post autor polymorphism otrzymał podziękowanie od:
Arnold_S
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez Arnold_S » piątek, 10 listopada 2017, 18:41

Zrozumiałem co robiłem, źle.
Niewłaściwe było to, że chciałem wywoływać funkcję wirtualną klasy z parametrem, w którym umieszczałem prywatny składnik :O Nie wiem co mi przysłoniło oczy hehhe. Poprostu nie mogę się do nich odwoływać z poza klasy, nawet wstawiając je jako argument funkcji należącej do tej klasy...tak to zrozumiałem.

Twoje przykłady z getterami i typedef-em są bardzo praktyczne. Dzięki za cierpliwość i pomoc :D
Avatar użytkownika
Arnold_S
Homos antropiczny
Homos antropiczny
 
Posty: 58
Dołączył(a): niedziela, 12 czerwca 2016, 23:22
Podziękował : 15
Otrzymał podziękowań: 0
System operacyjny: Win7 64b
Kompilator: C++ Builder 6, Rad Studio XE2
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez Arnold_S » poniedziałek, 13 listopada 2017, 00:12

Przepraszam, że piszę post pod postem ale mam dziwny problem.
Co do klas to wszystko zaczyna ładnie działać z jednym ale...Gdy próbuję kompilować to wyskakuje mi błąd:

ilink32 command line
c:\program files (x86)\embarcadero\rad studio\9.0\bin\ilink32.exe -L.\Win32\Debug;"c:\program files (x86)\embarcadero\rad studio\9.0\lib\Win32\debug";
"C:\PROJEKTY\klasy test2";"c:\program files (x86)\embarcadero\rad studio\9.0\lib\win32\release";"c:\program files (x86)\embarcadero\rad
studio\9.0\lib\win32\release\psdk";"C:\Program Files (x86)\Raize\CS5\Lib\RS-XE2\Win32";"C:\Users\Public\Documents\RAD Studio\9.0\DCP" -j.\Win32\Debug;
"c:\program files (x86)\embarcadero\rad studio\9.0\lib\Win32\debug";"C:\PROJEKTY\klasy test2";"c:\program files (x86)\embarcadero\rad
studio\9.0\lib\win32\release";"c:\program files (x86)\embarcadero\rad studio\9.0\lib\win32\release\psdk";"C:\Program Files
(x86)\Raize\CS5\Lib\RS-XE2\Win32";"C:\Users\Public\Documents\RAD Studio\9.0\DCP" -l.\Win32\Debug -v
-GA"C:\Users\unknown\AppData\Local\Temp\vfsCF30.tmp"="C:\PROJEKTY\klasy test2\Unit1.dfm" -aa -V5.0 -G8 -Tpe c0w32w rtl.bpi vcl.bpi memmgr.lib
sysinit.obj .\Win32\Debug\Project1.obj .\Win32\Debug\Unit1.obj , .\Win32\Debug\Project1.exe , .\Win32\Debug\Project1.map , import32.lib cp32mti.lib ,
, Project1.res
[ILINK32 Error] Error: Unresolved external 'kot::losuj_uszy()' referenced from C:\PROJEKTY\KLASY TEST2\WIN32\DEBUG\UNIT1.OBJ
[ILINK32 Error] Error: Unresolved external 'kot::losuj_oczy()' referenced from C:\PROJEKTY\KLASY TEST2\WIN32\DEBUG\UNIT1.OBJ
[ILINK32 Error] Error: Unresolved external 'kot::losuj_futro()' referenced from C:\PROJEKTY\KLASY TEST2\WIN32\DEBUG\UNIT1.OBJ
[ILINK32 Error] Error: Unable to perform link
Failed


Pojawia się tylko i wyłącznie wtedy gdy dołączam pliki nagłówkowe, a definicje są w oddzielnym pliku cpp. Natomiast gdy w jednym pliku nagłówkowym umieszczam deklaracje i definicje to wszystko działa pięknie. Czy oprócz normalnego include coś jeszcze muszę wyczarować?
Avatar użytkownika
Arnold_S
Homos antropiczny
Homos antropiczny
 
Posty: 58
Dołączył(a): niedziela, 12 czerwca 2016, 23:22
Podziękował : 15
Otrzymał podziękowań: 0
System operacyjny: Win7 64b
Kompilator: C++ Builder 6, Rad Studio XE2
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez polymorphism » poniedziałek, 13 listopada 2017, 11:57

Musisz dodać do projektu wszystkie niezbędne pliki .cpp (Add to project albo jakoś tak).
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez Arnold_S » środa, 22 listopada 2017, 00:42

Witam! Proszę o podpowiedź. Jeżeli w mojej klasie A chciałbym używać obiektu małej klasy B to lepiej ją zagnieździć? Chodzi mi o to aby obiekt zagnieżdżonej klasy B swobodnie mógł korzystać z funkcji i obiektów głównej klasy A i wice versa.
...I teraz pojawiają się schody bo nigdzie nie mogę znaleźć informacji jak zachować się w przypadku dziedziczenia i polimorfizmu. Przykład:

- główna klasa A dziedziczy od klasy abstrakcyjnej "znak".
- klasa A zawiera zagnieżdżone malutkie klasy B1, B2, B3.
- wydaje mi się, że małe klasy B1,B2, B3 będą korzystały z tych samych funkcji więc chętnie uczyniłbym je dziedzicami polimorficznej klasy "znaczek".

Jeżeli deklarację zagnieżdżonych klas umieszczę w prywatnej części klasy A, to jak miałaby wyglądać deklaracja polimorficznej klasy "znaczek" i dziedziczących od niej klas B1,B2,B3? Czy to zagnieżdżanie to praktyczny sposób? Czy jest jakiś prostszy sposób i mniej zagmatwany?
Avatar użytkownika
Arnold_S
Homos antropiczny
Homos antropiczny
 
Posty: 58
Dołączył(a): niedziela, 12 czerwca 2016, 23:22
Podziękował : 15
Otrzymał podziękowań: 0
System operacyjny: Win7 64b
Kompilator: C++ Builder 6, Rad Studio XE2
Gadu Gadu: 0
    Windows 7Firefox

Re: każda klasa w oddzielnym pliku...

Nowy postprzez polymorphism » środa, 22 listopada 2017, 12:30

to jak miałaby wyglądać deklaracja polimorficznej klasy "znaczek" i dziedziczących od niej klas B1,B2,B3?

Tak samo jak w przypadku klasy niezagnieżdżonej?

Czy to zagnieżdżanie to praktyczny sposób?

Jeśli nie chcesz sobie "brudzić" przestrzeni nazw klasą, która jest tylko na użytek innej klasy, to zagnieżdżanie ma sens.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox

Poprzednia strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 43 gości

cron