Как проектировать перегруженные функции-члены с помощью const и volatile при разработке API? - PullRequest
1 голос
/ 19 января 2012

Предположим, вы пишете небольшую библиотеку или API, которые будут распространяться на другие программы, это означает, что вы никогда не знаете, как другие программисты будут создавать объекты: будет ли такой объект постоянным, изменчивым, постоянным изменчивым или это будет просто обычный объект.

обычно, когда мы объявляем некоторый класс, мы делаем это так:

class A // THIS CLASS DOES NOT SUPPORT ANYTHING
{
public:
    int get() { return x; }
private:
    int x;
};

однако, если вы хотите, чтобы ваш класс поддерживал объекты const, вы перегружаете функцию-член квалификатором const:

class B // THIS CLASS SUPPORTS CONST OBJECTS
{
public:
    int get() { return x; }
    int get() const { return x; }
private:
    mutable int x;
};

еще больше, может быть, мы хотим также поддерживать volatile, но не const для нашего класса:

class C // THIS CLASS SUPPORTS VOLATILE OBJECTS
{
public:
    int get() { return x; }
    int get() volatile { return x; }
private:
    int x;
};

НО, что если пользователь будет использовать объект, который является постоянным или изменчивым, или Что если пользователь будет использовать объект, который является изменчивым и постоянным одновременно? тогда мы должны добавить поддержку этого тоже!

class D // THIS CLASS SUPPORTS CONST, VOLATILE AND CONST VOLATILE OBJECTS
{
public:
    int get() { return x; }
    int get() const { return x; }
    int get() volatile { return x; }
    int get() const volatile { return x; }
private:
    mutable int x;
};

Теперь давайте посмотрим, почему мы хотим, чтобы наш класс имел эти 4 перегрузки:

// EXAMPLE
int main()
{
    // figure 1
    const A a ;
    a.get(); // ERROR

    // figure 2
    volatile B b;
    b.get(); // ERROR

    // figure 3
    const volatile C c;
    c.get(); // ERROR

    // figure 4 where we finaly created a super class capable of anything!!
    const volatile D d;
    d.get(); // NOW IS OK!

    cin.ignore();
    return 0;
}

хорошо в этом последнем примере (рисунок 4) мы можем быть уверены, что наш класс может быть создан для любого типа это означает, что у других программистов не возникнет проблем при создании изменчивого, постоянного или изменчивого объекта const вашего класса!

мой вопрос: Это хорошая практика проектирования, чтобы перекрывать каждый метод четыре раза? если нет, то почему?

также, если у нашего класса есть, скажем, 20 методов, тогда у него будет 80 методов, когда вы перегрузите их все!

EDIT:

классы API реального мира делают такое? если нет, то как бы мы создали энергозависимый или постоянный энергозависимый объект этого класса, если, скажем, у нас есть такая потребность.

1 Ответ

4 голосов
/ 19 января 2012

Мое мнение таково, что в реальном мире:

  1. Volatile широко не используется, и когда оно есть, оно всегда изменяет основные типы.Но никогда не возражайте, поэтому вам никогда не нужно переопределять энергозависимую функцию-член.

  2. const следует добавить к функциям-членам, не думая о том, понадобится ли это const код клиента, но вместо этого подумайте, если операция, выполняемая функцией-членом, концептуально постоянна.Это называется const правильность :

    a.Прежде всего, функция должна делать только одну вещь.Может быть, одна сложная вещь, но описываемая как единое понятие.

    b.Затем спросите себя, изменяет ли эта вещь функция наблюдаемое состояние объекта.Если это так, то функция не должна быть постоянной.А если это не так, тогда объявите его как константу.

Когда клиентский код хочет использовать ваш класс, он будет иметь ссылку const, когда ему не разрешено изменятьсостояние объекта, и все будет просто работать.

Обратите внимание, что я говорил о наблюдаемом состоянии объекта, а не о фактическом содержимом переменных-членов: это детали реализации.

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