private virtual - do czego to służy?

0

Przykładowo mamy funkcję w class A:

private:
virtual int Command(int id) 
 { // by default }

potem chcę to rozbudować i podmienić:

class B : public A
{
 virtual int Command(int id) 
 { 
    if( id == 111 ) return mycode(); // moja robota
    else // standard pozostaje!
      return A::Command(int id); // tylko że to jest niedostępne, bo prywatne!
 }
}

I po co w ogóle to 'private' - do czego to służy?

Ostatecznie i tak mogę wejść w header i podmienić private na public - i co wtedy się stanie?

0

Po co w ogóle to 'private' - do czego to służy?

Może służyć do ukrycia implementacji (przy zachowaniu polimorfizmu), która nie powinna być dostępna dla pewnych klas potomnych.

#include <iostream>
#include <memory>

using namespace std;

class QuantumEntity
{
private:
    virtual void make_fussion() { cout << "Boom! on quantum level." << endl; };
};

class BaryonMatter : public QuantumEntity
{
private:
    void make_fussion() override { cout << "Boom! on atomic level." << endl; };
    friend int main(); 
};

class CarbonForm : public BaryonMatter
{
public:
    virtual void changeDNA() { cout << "Changing DNA of Carbon Form." << endl; }
    void make_fussion() override { cout << "CarbonForm cannot be fusion." << endl; };
};

class Animal : public CarbonForm
{
public:
    void changeDNA() override { cout << "Changing DNA of Animal." << endl; }
    void make_fussion() override { cout << "Animal cannot be fusion." << endl; };
};

class Cat : public Animal
{
public:
    void changeDNA() override { cout << "Changing DNA of Cat. I am the Mouse now." << endl; }
    void make_fussion() override { cout << "Cat cannot be fusion." << endl; };
};

int main()
{
    Cat Grizabella;
    Grizabella.changeDNA();
    Grizabella.make_fussion();

    BaryonMatter rock;
    rock.make_fussion(); 

    auto generic = make_unique<Animal>();
    generic->make_fussion();

    return 0;
}
0

"private:" wyraża intencję autora A, że Command będzie wywołane jedynie przez kod zaimplementowany w klasie A i nikt inny go nie powinien wywoływać.
Klasy potomne mają prawo napisać Command, ale nie powinny jej wywołać.
Klasa potomna, może "upublicznić" Command, ale to nie problem, bo najważniejsze jest wyrażenie intencji autora w postaci kodu.

Prosty scenariusz:

#include <iostream>
#include <memory>

class Base
{
public:
   void doSomeLogic()
   {
       for (int i = 0 ; i < 5; ++i) {
            action(i);
       }
   }
private:
   virtual void action(int i) = 0;
};

class Child : public Base
{
public:
    void foo()
    {
        action(3);
    }

    void action(int i) override {
        std::cout << i << '\n';
    }
};

int main() {
    std::unique_ptr<Base> p = std::make_unique<Child>();

    p->doSomeLogic();
    // p->action(1); // error: 'virtual void Base::action(int)' is private within this context

    return 0;
}

W patryce takie coś ma małą wartość i rzadko to widuję.

W takich scenariuszach zamiast dziedziczenia lepiej stosować zawieranie.

0

Moim zdaniem użycie: private virtual jest błędem programisty.
Sama możliwość produkowania takich niewypałów wynikła pewnie z niedopatrzenia projktanów C++;
poprawnie taki kod powinien być blokowany przez kompilator, jako błąd: incorrect context to use of 'virtual' keyword.

A nawet gorzej: samo to 'private' nie powinno wcale istnieć w definicji class,
bo takie coś potem uniemożliwia naprawianie błędów w bibliotekach.

Prywatne są zmienne lokalne, i nic ponadto.

fun()
{
int x; // to jest private dla tej funkcji
x = ...
}

0
nowewww napisał(a):

Moim zdaniem użycie: private virtual jest błędem programisty.

Dałem ci przykład gdzie to ma jakiś sens.

Zresztą sam koncept public/protected/private jest krytykowany (IMO słusznie).
Większość języków nie ma czegoś takiego i nikt nie narzeka.

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