• 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

VPS Starter Arubacloud
0 głosów
278 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 Ekspert (212,630 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 Mędrzec (172,590 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 Ekspert (212,630 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 Ekspert (212,630 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 Mądrala (5,650 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 Ekspert (212,630 p.)
Na pewno nie jest to przeciążanie operatorów.
komentarz 6 października 2016 przez Ditrix Mądrala (5,650 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 Ekspert (212,630 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
1 odpowiedź 118 wizyt
pytanie zadane 18 kwietnia 2020 w C i C++ przez NewEraOfPeace Gaduła (4,790 p.)
+1 głos
1 odpowiedź 332 wizyt
pytanie zadane 27 grudnia 2017 w C i C++ przez MAGNET Nowicjusz (160 p.)
0 głosów
4 odpowiedzi 6,003 wizyt
pytanie zadane 30 stycznia 2016 w C i C++ przez Mateo500 Nowicjusz (150 p.)

92,452 zapytań

141,262 odpowiedzi

319,085 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...