Может ли изменение спецификатора доступа в программе изменить поведение программы? - PullRequest
4 голосов
/ 05 апреля 2019

Интересно, есть ли в программе на С ++ случаи, когда изменение спецификатора доступа (открытый / защищенный / закрытый) в коде приводит к изменению поведения этой программы?

Ответы [ 3 ]

4 голосов
/ 05 апреля 2019

Шаблоны позволяют вам делать разные вещи в зависимости от того, доступен элемент или метод или нет. В качестве случайного примера рассмотрим следующее:

#include <type_traits>
#include <iostream>

struct foo_private {
    private:
        foo_private() {}
};
struct foo_public {
    public:
        foo_public() {}
};

int main() {        
    std::cout << std::is_default_constructible<foo_private>::value;
    std::cout << std::is_default_constructible<foo_public>::value;       
}
3 голосов
/ 05 апреля 2019

Один интересный пример, который, по сути, происходит чисто во время выполнения. Это означает, что программе необходимо каким-то образом знать некоторую информацию, полученную из уровня доступа: за [exc.handle] /3.2, обработчик исключения соответствует объекту исключения, еслиобработчик принимает однозначный и публичный базовый класс типа класса объекта исключения.

#include <iostream>

class Base {};

void test(void (*thrower)()) {
    try {
        thrower();
    } catch (Base&) {
        std::cout << "Caught a Base." << std::endl;
    } catch (...) {
        std::cout << "Not a Base?" << std::endl;
    }
}

class D1 : public Base {};
class D2 : private Base {};

int main() {
    std::cout << "Test D1" << std::endl;
    test([]() { throw D1{}; });
    std::cout << "Test D2" << std::endl;
    test([]() { throw D2{}; });
}

Это печатает:

Test D1
Caught a Base.
Test D2
Not a Base?

... даже если толькоразница между D1 и D2 заключается в изменении ключевого слова спецификатора доступа.

1 голос
/ 05 апреля 2019

Да, это может произойти, если кто-то СФИНАЕ откажется от вызова этой функции. Например:

class Cat {
public:
    void purr() const;

public:
    void hiss() const;
};

using prefer_overload_t = int;
using backup_overload_t = long;

template <typename T>
auto react(prefer_overload_t, T const& t)
    -> decltype(t.purr())
{
    return t.purr();
}

template <typename T>
void react(backup_overload_t, T const& t)
{
    t.hiss();
}

int main() {
    Cat cat;
    react(prefer_overload_t{}, cat);
}

Live on Godbolt .

Если функция purr имеет общедоступный доступ, это вызывает cat.purr(). Если функция purr имеет закрытый доступ, это вызывает cat.hiss().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...