Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Polimorfizm, wieloznaczność.

Ostatnio zmodyfikowano 2019-04-10 19:13
Autor Wiadomość
CPnHorror
Temat założony przez niniejszego użytkownika
[C++] Polimorfizm, wieloznaczność.
» 2019-04-05 06:58:35
Witam.
Zacząłem ostatnio uczyć się polimorfizmu i natrafiłem na niezłą przeszkodę z tego co wyczytałem jest to tzw. problem diamentu lecz zważywszy na to, że nie jestem pewien tego terminu określę swój problem.

Stworzyłem hierarchię działającą na zasadzie poniższego schematu

          Figure
      /            \
Rectangle    Circle
      \            /
          Button


chciałbym móc utworzyć Button o kształcie prostokąta ALBO koła i tu pojawia się wieloznaczność.
próbowałem odnieść się do obiektu wyższego poprzez :: ale kompilator odmawia i widzi dwie funkcje dwóch obiektów mimo, że tworzę w konstruktorze Buttona tylko jeden.

dorzucę kod z paru plików.

MAIN.cpp
C/C++
#include "main.hpp"
using namespace std;

Rect * recta;
Circle * cir;
Button * But;

int main()
{
    recta = new Rect( sf::Vector2f( 500, 300 ), sf::Vector2f( 100, 76 ), sf::Color::Blue );
    cir = new Circle( sf::Vector2f( 100, 50 ), 20, sf::Color::Red );
    But = new Button( false, false, sf::Vector2f( 700, 50 ), 34.f, sf::Color::Green );
   
    while( RWin.isOpen() )
    {
        RWin.clear();
       
        recta->Draw( & RWin );
        cir->Draw( & RWin );
        But->Draw( & RWinL );
       
        RWin.display();
    }
   
    delete recta;
    delete cir;
    delete But;
    return( 0 );
}

FIGURE.HPP
C/C++
#ifndef Figure_hpp
#define Figure_hpp

#include <iostream>
#include <SFML/Graphics.hpp>

class Figure
{
public:
    sf::Vector2f Pos;
    sf::Color Color;
    Figure * Next;
   
    Figure();
    Figure( sf::Vector2f PosL, sf::Color ColorL );
    virtual ~Figure();
    void virtual Draw( sf::RenderWindow * RWinL );
};

#endif // Figure_hpp

FIGURE.CPP
C/C++
#include "Figure.hpp"
using namespace std;

Figure::Figure()
{
}

Figure::Figure( sf::Vector2f PosL, sf::Color ColorL )
{
    cout << "\nstworzylem figure";
}

Figure::~Figure()
{
    cout << "\nzniszczylem figure";
}

void Figure::Draw( sf::RenderWindow * RWinL )
{
    cout << "\nbrak ksztaltu...";
}


CIRCLE.HPP
C/C++
#ifndef Circle_hpp
#define Circle_hpp
#include "Figure.hpp"
#include <iostream>
using namespace std;

class Circle
    : public virtual Figure
{
public:
    float Radius;
    Circle * Next;
   
    Circle();
    Circle( sf::Vector2f PosL, float RadiusL, sf::Color ColorL );
    virtual ~Circle();
    void Draw( sf::RenderWindow * RWinL );
   
};

#endif // Circle_hpp

CIRCLE.CPP
C/C++
#include "Circle.hpp"
using namespace std;

Circle::Circle()
{
   
}

Circle::Circle( sf::Vector2f PosL, float RadiusL, sf::Color ColorL )
    : Figure( PosL, ColorL )
{
    cout << "\nstworzylem kolo";
}

Circle::~Circle()
{
    cout << "\nzniszczylem kolo";
}

void Circle::Draw( sf::RenderWindow * RWinL )
{
    cout << "\nnarysowalem kolo";
}

RECTANGLE.HPP
C/C++
#ifndef Rectangle_hpp
#define Rectangle_hpp
#include "Figure.hpp"
#include <iostream>
using namespace std;

class Rect
    : public virtual Figure
{
public:
    sf::Vector2f Size;
    sf::RectangleShape * Img;
    Rect * Next;
   
    Rect();
    Rect( sf::Vector2f PosL, sf::Vector2f SizeL, sf::Color ColorL );
    virtual ~Rect();
    void Draw( sf::RenderWindow * RWinL );
};

#endif // Rectangle_hpp

RECTANGLE.CPP
C/C++
#include "Rectangle.hpp"
using namespace std;

Rect::Rect()
{
}

Rect::Rect( sf::Vector2f PosL, sf::Vector2f SizeL, sf::Color ColorL )
    : Figure( PosL, ColorL )
{
    cout << "\nstworzylem rect";
}

Rect::~Rect()
{
    cout << "\nzniszczylem rect";
}

void Rect::Draw( sf::RenderWindow * RWinL )
{
    cout << "\nnarysowalem rect";
}

BUTTON.HPP
C/C++
#ifndef Button_hpp
#define Button_hpp
#include "Figure.hpp"
#include "Rectangle.hpp"
#include "Circle.hpp"
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;

class Button
    : public Circle
     , public Rect
{
public:
    bool Clicked;
    bool Pressed;
    Button * Next;
   
    Button();
    Button( bool IsClick, bool IsPress, sf::Vector2f PosL,
    sf::Vector2f SizeL, sf::Color ColorL );
    Button( bool IsClick, bool IsPress, sf::Vector2f PosL,
    float RadiusL, sf::Color ColorL );
    ~Button();
    void Draw( sf::RenderWindow * RWinL );
};

#endif // Button_hpp

BUTTON.CPP
C/C++
#include "Button.hpp"
using namespace std;

Button::Button( bool IsClick, bool IsPress, sf::Vector2f PosL,
sf::Vector2f SizeL, sf::Color ColorL )
    : Rect( PosL, SizeL, ColorL )
{
    cout << "\nstworzylem button rect'owy";
}

Button::Button( bool IsClick, bool IsPress, sf::Vector2f PosL,
float RadiusL, sf::Color ColorL )
    : Circle( PosL, RadiusL, ColorL )
{
    cout << "\nstworzylem button cirl'owy";
}

Button::~Button()
{
    cout << "\nzniszczylem button";
}

void Button::Draw( sf::RenderWindow * RWinL )
{
    //  głupie głupoty ...
    if( Circle != NULL )
         Draw( RWinL );
   
    if( Rect != NULL )
         Draw( RWinL );
   
    // no cholera jasna...
}
P-174333
pekfos
» 2019-04-05 11:10:25
chciałbym móc utworzyć Button o kształcie prostokąta ALBO koła i tu pojawia się wieloznaczność.
Takie dziedziczenie nie ma sensu. Twój przycisk jest jednocześnie prostokątem i kołem. Przycisk powinien nie dziedziczyć po figurze, tylko zawierać wskaźnik na figurę. Wtedy możesz określić dowolną figurę jako kształt przycisku i nie masz bezsensownych relacji między klasami.
P-174334
CPnHorror
Temat założony przez niniejszego użytkownika
» 2019-04-05 23:17:30
No dobrze, tak też zrobiłem. Ale czy istnieje jakaś możliwość rozwiązania problemu diamentu na zasadzie dziedziczenia i uniknięcia wieloznacznosci w c++?
P-174340
pekfos
» 2019-04-06 00:09:31
kompilator odmawia i widzi dwie funkcje dwóch obiektów mimo, że tworzę w konstruktorze Buttona tylko jeden.
Button jest z definicji prostokątem i kołem. Wszystkie podobiekty są tworzone w konstruktorze i to że możesz określić sam prostokąt na liście inicjalizacyjnej wynika z tego, że koło ma domyślny konstruktor, który zresztą nie inicjalizuje poprawnie wszystkich składowych. Jak chcesz rozróżniać tu przycisk kwadratowy od okrągłego, to możesz to zrobić tylko przez ręczne zapisanie tej informacji.

Sensowny przykład dziedziczenia wirtualnego i "diamentu" masz w bibliotece standardowej. Zobacz na przykład jak jest zdefiniowane std::fstream.
P-174341
CPnHorror
Temat założony przez niniejszego użytkownika
» 2019-04-10 19:13:24
Dziękuję za odpowiedź pekfos.
Pozdrawiam.
P-174376
« 1 »
  Strona 1 z 1