Атрибуты функции-члена D - PullRequest
3 голосов
/ 26 декабря 2011

Рассмотрим:

class B
{
public:
    int i = 4;
}

class A
{
public:
    B b;

    this()
    {
        b = new B;
    }

    ref B f()
    {
        return b;
    }
}

Класс хранения ref перед функцией-членом f избыточен, верно? Объекты класса всегда передаются по ссылке, поэтому возвращение B и ref B эквивалентно?

Второй: pure функции-члены? Чистая функция - возвращать только то, что зависит от аргументов. Таким образом, он не должен зависеть от каких-либо данных-членов класса, поскольку они могут изменить выходные данные функции даже для тех же передаваемых аргументов. Таким образом, pure функция-член, следовательно, также является static функцией-членом? (обратное не может быть правдой)

В-третьих: в чем разница между const и неизменным классом-членом? Различать вызовы функций-членов неизменяемых и const объектов класса? Семантически это равносильно тому, что мы не можем изменить элементы данных с обоими атрибутами, верно?

Четвертый: я должен добавить как можно больше атрибутов функции? Как pure, const или immutable, nothrow и final?


Круто, только что обнаружил это работает:

inout(B) f() inout
{
    return b;
}

Ответы [ 3 ]

5 голосов
/ 26 декабря 2011

ref B f() - это функция, которая возвращает B по ссылке. B является ссылкой на класс. Поэтому он возвращает ссылку на класс по ссылке. Это не глупость в D, потому что ссылки на классы могут быть восстановлены:

auto a = new A;
a.f() = new B; // rebinds a.b, possible due to return by ref

Аналогично, вы также можете иметь указатели на ссылки на классы в D:

class A
{
    B b;

    /* ... */

    B* f()
    {
        return &b;
    }
}

auto a = new A;
B* b = a.f(); // pointer to reference to instance of class B
*b = new B; // updates a.b

Для pure функций-членов неявный ссылочный параметр this - это просто еще один параметр. Это считается частью ввода. При том же объекте this и тех же обычных параметрах выходные данные всегда остаются одинаковыми.


С помощью функции-члена const вы не знаете, является ли объект this изменчивым или неизменным. Это может быть либо - функция-член const обещает не изменять его в любом случае. При использовании функции-члена immutable объект this всегда неизменен. Таким образом, ссылка this может передаваться как неизменяемый аргумент другой функции или назначаться неизменяемым переменным.


При принятии решения о том, когда следует заботиться о const, immutable, pure и nothrow, вы должны учитывать, действительно ли вам нужны эти различные гарантии в коде клиента. Если вы пишете библиотеку для общего пользования, вы, вероятно, этого не знаете, поэтому в этих случаях лучше предоставить как можно больше гарантий.

Ситуация, возможно, иная для final. Используйте его, если вы не хотите, чтобы клиентский код случайно переопределял функцию, которая не имеет смысла переопределять или не предназначена для переопределения, или когда вы хотите дать компилятору больше возможностей для оптимизации вызовов этой функции. Финальные функции, которые не переопределяют какие-либо функции (с override) и не реализуют никаких интерфейсных функций, не обязательно должны быть виртуальными функциями, что снижает накладные расходы на вызов.

3 голосов
/ 26 декабря 2011

Класс хранения ref перед функцией-членом f избыточен, верно? Объекты класса всегда передаются по ссылке, поэтому возвращение B и ref B эквивалентно?

Добавление ref позволяет изменить поле b (фактическую ссылку, а не только его содержимое), написав: a.f() = new B();

Второе: pure функции-члены?

Я считаю, что чистые методы рассматривают this как еще один аргумент.

В-третьих: в чем разница между const и неизменным классом-членом? Различать вызовы функций-членов неизменяемых и const объектов класса? Семантически это равносильно тому, что мы не можем изменить элементы данных с обоими атрибутами, верно?

Да, но версия immutable имеет более строгие гарантии.

В-четвертых: я должен добавить как можно больше атрибутов функции? Как pure, const или immutable, nothrow и final?

Добавьте столько атрибутов, сколько вы ожидаете, будет полезно при использовании написанного вами кода. (Обратите внимание, что текущая реализация не очень хороша в обнаружении избыточных атрибутов.)

2 голосов
/ 26 декабря 2011

так что возвращение B и ref B эквивалентны?

Нет. ref заставляет функцию возвращать lvalue, что позволяет:

auto a = new A;
auto b = new B;
b.i = 55;
a.f() = b;
writeln(a.b.i); // 55

pure функции-члены?

Функция-член может рассматриваться как свободная функция, принимающая экземпляр в качестве одного из параметров.

   class A { pure void f(int others) immutable; }
<=>
   class A { ... }
   pure void f(immutable(A) this, int others);

Таким образом, функция-член по-прежнему может считывать и изменять (для слабо-чистых) this, поскольку это только один из параметров.


В чем разница между const и неизменяемым классом-членом?

Не уверен, что вы имеете в виду ☺


я должен добавить как можно больше атрибутов функции?

Вы должны добавить атрибуты функции, которые лучше всего описывают вашу функцию. Если функция никогда не будет переопределена, добавьте final. Если никогда не выдаст какие-либо исключения, добавьте nothrow и т. Д.

(BTW, pure, nothrow и @safe могут быть выведены, если функция является функцией шаблона.)

...