Проверка спецификатора доступа для виртуальных функций [duplicate]

Ваша ссылка неверна. Ваша референтная база данных должна указывать на fnBOM ..... вместо «GTjrWgpKjoeXUt4JdBJTYP1JkVT2»

       final DatabaseReference receiver = 
       users.child("GTjrWgpKjoeXUt4JdBJTYP1JkVT2").child("fnBom...");

, и вы можете хранить каждый дочерний объект на арифметике, а последний элемент доступа - arraylist

        myArrayList.get(myArrayList.size()-1);
7
задан irappa 21 May 2013 в 12:19
поделиться

4 ответа

Как многие из парней отметили, что это законно.

Однако, часть «IS-A» не так проста. Когда дело доходит до «динамического полиморфизма», имеет место соотношение «IS-A», I.e. все, что вы можете сделать с Super, вы также можете делать с Derived экземпляром.

Однако в C ++ у нас также есть то, что часто называют статическим полиморфизмом (шаблоны, большую часть времени). Рассмотрим следующий пример:

class A {
public:
    virtual int m() {
        return 1;
    }
};

class B : public A {
private:
    virtual int m() {
        return 2;
    }
};

template<typename T>
int fun(T* obj) {
    return obj->m();
}

Теперь, когда вы пытаетесь использовать «динамический полиморфизм», все выглядит нормально:

A* a = new A();
B* b = new B();

// dynamic polymorphism
std::cout << a->m(); // ok
std::cout << dynamic_cast<A*>(b)->m(); // ok - B instance conforms A interface
// std::cout << b->m(); fails to compile due to overriden visibility - expected since technically does not violate IS-A relationship

... но когда вы используете " статический полиморфизм "вы можете сказать, что отношение« IS-A »больше не выполняется:

A* a = new A();
B* b = new B();

// static polymorphism
std::cout << fun(a); // ok
//std::cout << fun(b); // fails to compile - B instance does not conform A interface at compile time

Итак, в конечном итоге изменение видимости метода является« довольно законным », но это одна из уродливых вещей в C ++, что может привести к ловушке.

2
ответ дан Eugene Loy 21 August 2018 в 04:03
поделиться

Да, это разрешено до тех пор, пока подпись будет одинаковой. И , на мой взгляд, , да, вы правы, переопределение видимости (например, public -> private) прерывает IS-A. Я полагаю, что у Скотта Майерса «Эффективная серия C ++» есть обсуждение этого вопроса.

1
ответ дан AlexK 21 August 2018 в 04:03
поделиться

Да, это законно, доступность проверяется статически (не динамически):

class A {
public:
    virtual void foo() = 0;
private:
    virtual void bar() = 0;
};

class B : public A {
private:
    virtual void foo() {} // public in base, private in derived
public:
    virtual void bar() {} // private in base, public in derived
};

void f(A& a, B& b)
{
    a.foo(); // ok
    b.foo(); // error: B::foo is private
    a.bar(); // error: A::bar is private
    b.bar(); // ok (B::bar is public, even though A::bar is private)
}

int main()
{
    B b;
    f(b, b);
}

Теперь, зачем вы хотите это сделать? Это имеет значение только при непосредственном использовании производного класса B (второй параметр f()), а не через базовый интерфейс A (первый параметр f()). Если вы всегда используете абстрактный A интерфейс (как я бы рекомендовал в целом), он по-прежнему соответствует режиму «IS-A».

3
ответ дан gx_ 21 August 2018 в 04:03
поделиться

Разрешено в обоих направлениях (т. е. от private до public И от public до private).

С другой стороны, я бы сказал, что это не нарушить связь IS-A. Я основываю свой аргумент на двух фактах:

  • , используя дескриптор Base& (или Base*), у вас есть точно такой же интерфейс, что и до
  • , вы могли бы прекрасно ( если вы хотите) ввести прямой метод, который public и вызов метода private напрямую в любом случае: тот же эффект с большим количеством ввода
3
ответ дан Matthieu M. 21 August 2018 в 04:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: