• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Dostęp do metod wirtualnych

0 głosów
97 wizyt
pytanie zadane 6 października 2016 w C i C++ przez Mikeros Początkujący (320 p.)
zamknięte 8 października 2016 przez Mikeros

Witam, ostatnio zastanawiałem się trochę nad hermetyzacją metod wirtualnych. Czytając trochę zagranicznych stron, w większości znajdowałem odpowiedź, że dobrze jest metody wirtualne opatrzyć dostępem private lub protected. Okej - problem pojawia się natomiast w wywołaniu metody wirtualnej klasy pochodnej poprzez wskaźnik do obiektu klasy bazowej. Jeśli metoda jest private/protected w klasie bazowej, to kompilator "zaprotestuje", pomimo, że metoda w klasie pochodnej jest public. Wiem mniej więcej jak działa kompilator w tym przypadku, jednak nie widzę rozwiązania takiej sytuacji (oprócz nadania dostępu public, co uważam za niezbyt dobry pomysł). Czy są wówczas jakieś sposoby na osiągniecie danego celu? Czy może hermetyzacja metod wirtualnych rządzi się innymi prawami?

Przykładowy kod:

#include <iostream>
using namespace std;
class A
{
    private:
    virtual void funkcja() 
	{
        cout<<"A::funkcja wywolane" <<endl;
    }
    
};
class B:public A
{	
	public:
    void funkcja() {
        cout<<"B::funkcja wywolane"<<endl;
    }
};
int main()
{
    A *a = new B();
    a->funkcja(); //kompilator "mysli" ze ma to byc funkcja z klasy A

    return 0;
}

 

komentarz zamknięcia: Wyczerpanie tematu.
komentarz 8 października 2016 przez Mikeros Początkujący (320 p.)
Myślę, że temat wyczerpany. Dziękuję za pomoc. Zamykam.

2 odpowiedzi

0 głosów
odpowiedź 6 października 2016 przez Ehlert Szeryf (85,580 p.)
wybrane 8 października 2016 przez Mikeros
 
Najlepsza

Dla mnie to takie trochę niedogranie co do implementacji... Masz obiekt klasy bazowej. Posiada on metodę. Nie wiesz jak ona będzie wyglądać, ale jesteś pewny że nie będzie dostępna z zewnątrz. 

I przy dziedziczeniu z klasy bazowej nagle ta metoda ma modyfikator public i ciało funkcji. Osobiście nie widzę w tym sensu. 

komentarz 6 października 2016 przez Mikeros Początkujący (320 p.)
Ale jeśli jest to np. funkcja czysto wirtualna i nie miałaby ona ciała, to dlaczego miałaby być widoczna? Nie wiem, czy to prawda, ale podobno da się wywołać taką funkcję bez ciała, a skutki są nieznane, więc nadanie dostępu private mogłoby zapobiec jej wywołaniu.
komentarz 6 października 2016 przez Criss VIP (102,820 p.)
edycja 6 października 2016 przez Criss
Przede wszystkim, to nie da się utworzyć obiektu klasy zawierającej metodę "bez ciała" . Więc nie wywołałasz takiej metody.
Tzn. da się ale ciężko to zrobić przez przypadek. Chyba się da. Upewnie się w domu
komentarz 6 października 2016 przez Ehlert Szeryf (85,580 p.)
#include <iostream>

class BaseObject{

public:

    virtual void foo() = 0;

    BaseObject(){}
    ~BaseObject(){}

};

class New : public BaseObject
{

public:
    New():BaseObject()
    {}
    ~New();
};

int main()
{
    BaseObject * i = new New();
    i->foo();
    return 0;
}

 

error: invalid new-expression of abstract class type ‘New’
     BaseObject * i = new New();
                              ^

note:   because the following virtual functions are pure within ‘New’:
 class New : public BaseObject{
       ^

note:     virtual void BaseObject::foo()
     virtual void foo() = 0;
                  ^

G++ mówi i tłumaczy sam za siebie. 

komentarz 6 października 2016 przez Mikeros Początkujący (320 p.)
Przyznam się, że takiej metody samemu nie próbowałem odpalić. Masz rację - moje źródło było błędne. Czyli wychodziłoby na to, że metody czysto wirtualne mogą spokojnie być publiczne? A wracając do sytuacji przeze mnie przedstawionej, to jeśli jednak jakimś cudem zdarzyłaby się taka sytuacja, to da się to rozwiązać?

PS: Ogólnie to za niewiedzę przepraszam, póki co jestem amatorem i w sumie dlatego tu jestem :D
komentarz 6 października 2016 przez Ehlert Szeryf (85,580 p.)

Chwała Ci za to że jesteś amatorem, pytasz, a już wgl za to, że łapiesz się za metody wirtualne.

Jak widzisz kompilator nie dopuszcza takiej sytuacji. W standardzie C++11 doszły takie mechanizmy jak final (dla ostatecznej postaci metody bez możliwości nadpisania), i override.

0 głosów
odpowiedź 6 października 2016 przez Ditrix Gaduła (4,310 p.)
Wysnułem taką mała diagnozę, pewnie o tym wiesz, ale jeśli nie to.

Zapis A* a = new B(); oznacza, to, że tak na prawdę obiekt a jest typem B. Ale iż B dziedziczy od klasy A, to kompilator przy wywołaniu metody a->funkcja(); najpierw sprawdzi czy ta metoda jest w klasie A, a dopiero później czy jest w klasie B. Jeśli się okaże, że metoda funkcja() jest w klasie B i w klasie A, to wywoła funkcję z klasy B. Fachowo nazywa się to przeciążenie operatorów z tego co pamiętam, wywoływana najbardziej odpowiednia funkcja.

Więc moim zdaniem, kompilator widzi w klasie A metodę funkcja(), ale nie ma do niego bezpośrednio dostępu, wiec wyskakuje błąd. Taka kolejność zdarzeń.

Jeśli się mylę niech ktoś doświadczony poprawi :D
komentarz 6 października 2016 przez Ehlert Szeryf (85,580 p.)
Na pewno nie jest to przeciążanie operatorów.
komentarz 6 października 2016 przez Ditrix Gaduła (4,310 p.)
Faktycznie masz rację. Przeciążenie było by wtedy, gdy funkcje miały by tę samą nazwę, ale inne parametry.
komentarz 6 października 2016 przez Ehlert Szeryf (85,580 p.)

To jest przeciążanie metod. Przeciążanie operatorów to co innego angry

komentarz 6 października 2016 przez yarr Nowicjusz (100 p.)

Chciałbym tylko wyjaśnić różnicę między kilkoma pojęciami:

- przeciążenie operatora

- przeciążenie funkcji/metody

- nadpisanie funkcji/metody 

Przeciążenie operatora:

Często tego się używa, aby wskazać jak dane operatory mają się zachowywać wobec własnych typów (klas). Dajmy taki przykładzik, mamy klasę Hours i chcemy, aby po dodaniu do siebie minut 00:30:00 + 00:60:00 wychodził nam wynik 01:30:00, a nie 00:90:00. Dlatego będziemy przeciążać operator +.

Przeciążenie funkcji/metody:

Tego fajnie używać jeżeli nie chcemy nazbyt komplikować nazw metody, czy funkcji. Fajnie to widać w bibliotece SFML, gdzie mamy metodę "setPosition", która w jednym wariancie przyjmuje argumenty typu sf::Vector2f, a w drugim double width, double height. Przeciążanie metod następuje w ciele tej samej klasy.

Nadpisanie funkcji/metody:

Tutaj, najkrócej mówiąc, opisujemy zachowanie danej metody w klasie pochodnej.

Np. W Javie są interfejsy, których metody trzeba nadpisać. W C++ mamy metody czysto wirtualne czyli virtual metoda() = 0; W klasie pochodnej programista będzie musiał nadpisać pole "metoda()".

Mam nadzieję, że pomogłem :)

Podobne pytania

0 głosów
4 odpowiedzi 752 wizyt
pytanie zadane 30 stycznia 2016 w C i C++ przez Mateo500 Nowicjusz (150 p.)
0 głosów
1 odpowiedź 43 wizyt
–1 głos
1 odpowiedź 54 wizyt
pytanie zadane 12 stycznia w C i C++ przez timrh Mądrala (6,080 p.)
...