Перевод из Java в с++

137
24 сентября 2019, 17:40

Имеется такой класс:

public class Env
{
    private Hashtable table;
    protected Env prev;
    public Env(Env n)
    {
        table = new HashTable();
        prev = n;
    }
}

Вопрос в том, как передавать через конструктор объект этого же типа в с++?

Answer 1

Нужно понимать, что в с++ лучше использовать не обьекты напрямую а указатели либо ссылки. (объект - непрерывный участок в памяти, если в коде объект без указателя - он встраивается в scope-область видимости другого обьекта, для "самостоятельности" [т.е. что б не был встроен] нужно использовать указатель либо ссылку) Просто нужно добавить в местах обьявления обьектов - указатель(звёздочка). Кстати - new - возращает указатель. Для упрощения - в java тоже передаётся указатель, но синтаксиз упростили.

class Env
{
    private: Hashtable * table;
    protected: Env * prev;
    public: Env(Env * n)
    {
        table = new HashTable();
        prev = n;
    }
}

Запись Hashtable table; валидна, но обьект в таком случае будет создан и уничтожен неявно (new не требуется), и обьект имеет "стационарное место", т.е. его нельзя прямо так "копировать". В зависимости от конкретной ситуации так можно или нельзя делать (нужно понимать зона видимости и выход за неё, для table без new можно, для prev нельзя т.к. присвоение идет). Можно отдельно почитать про обьекты в с++. В большинстве случаев проще использовать * при передаче обьектов.

Я иногда путаю названия ссылка & и указатель *. Указатель может быть null. Тут речь идет об указателе, который ссылается на обьект. Вместо точки при указателе прийдётся писать -> (например table->toString()). Работать с ссылочным типом или с обьектом без указателя в с++ - несколько сложнее (зато там привычная точка).

UPD ещё немного. В с++ по умолчанию нету уборщика мусора в отличии от java - колличество new должно позже равнятся колличеству delete (что б небыло утечки памяти), но так же существует уборщик в виде отдельных библиотек.

Answer 2

При переводе кода с одного языка на другой возникает множество нюансов, особенно когда языки не имеют между собой какого-то родственного отношения.

В Java используются ссылочные типы данных, т.е. для записи вида public Env(Env n) фактически происходит передача ссылки (читай как адреса) объекта n в конструктор класса Env. Т.е. непосредственно до начала кода самого конструктора никакого копирования пользовательских данных ещё нет.

При этом стоит иметь в виду ещё такую особенность, что в Java используется сборщик мусора (Garbage Collector), и (по большей части) нет необходимости следить за временем жизни объектов, если ссылка на объект доступна, то и сам объект живой.

Суть вашего конструктора - формирование некоего линейного однонаправленного списка. Каждый новый объект Env создаёт таблицу и запоминает переданный аргумент, как некий предыдущий объект. Здесь стоит учесть тот вариант, что вызов Env(null) по сути начинает новый список, теряя все предыдущие объекты, если их не запомнить где-то дополнительно.

Учитывая необходимость передачи null в конструктор, подходящим вариантом использования в с++ будет указатель. Но так как в С++ нет сборщика мусора, а следить за валидностью объектов по сырым указателям не очень благодарная работа в современном мире, наиболее эквивалентным способом здесь будет использование умного указателя, т.е. обёртки вида std::shared_ptr (объект жив, пока доступен указатель и объект не копируется при копировании указателей, почти как в Java!) над вашим Env. А для table как приватного члена разумнее вовсе отказаться от указателя и хранить его по значению. Таким образом, результирующий код на C++, максимально близкий по поведению коду Java мне видится таким:

#include <memory>
class Hashtable { /* */ };
class Env
{
public:
    Env(std::shared_ptr<Env> n)
    {
        prev = n;
    }    
protected:
    std::shared_ptr<Env> prev;
private: 
    Hashtable table;    
};

Можно заметить, что в С++ отпала необходимость создавать явно объект table, т.к. он хранится в классе по значению, и в конструкторе Env создаётся конструктором по умолчанию (по сути то же, что в Java делается вызовом new HashTable();)

READ ALSO
Как реализовать сохранение SurfaceView в файл?

Как реализовать сохранение SurfaceView в файл?

Я рисую прямоугольники с использованием Canvas, динамически перемещаю и изменяю SurfaceView, я использую кнопку для сохранения("Save")

161
Вложеный масив в Retrofit

Вложеный масив в Retrofit

Не часто работал с Retrofit-м, поэтому еще плохо знаю всеНедавно добавил в бекенд пагинацию и следовательно в клиентов изменился json ответ

143
Работа с полигонами в google map на андроид

Работа с полигонами в google map на андроид

У меня есть куча координат в таком виде: ((759007919, 114

167