c ++ Назначение объектов в объявлении объекта - PullRequest
2 голосов
/ 19 марта 2011

Я родом из Java и недавно решил попробовать создать приложение C ++ Qt GUI "для удовольствия".Я боролся со многими тонкими различиями между Java и c ++, но я многому научился.

Я пытаюсь максимально приблизиться к синтаксису "java-style" в моем C ++ кодировании,Хотя это может или не может быть "лучшей практикой" для C ++, я чувствую, что это помогает при обучении сохранять семейный и последовательный синтаксис.Один из переносов синтаксиса Java заключается в следующем:

//Java
MyObject o = new MyObject();

//C++
MyObject o = MyObject();

Теперь я понимаю, что в C ++ есть синтаксическое сокращение для вышеупомянутого:

//C++
MyObject o();

Это хорошо и все, но, как я уже сказалЯ пока не хочу использовать другой синтаксис.Все работало нормально, но я получил сюрприз, когда попробовал следующий код Qt:

QString filepath = "C:\\somefile";
QFile file = QFile(filepath);

И получил ошибку компиляции:

c:\QtSDK\Desktop\Qt\4.7.2\mingw\include/QtCore/qfile.h:195: error: 'QFile::QFile(const QFile&)' is private within this context

Я прочитал документы Qt и обнаружил, чтодействительно нет открытого конструктора QFile :: QFile (const QFile &).Там, где мой код ранее работал для других классов, был такой конструктор.Здесь я могу сделать предположение и сказать, что строка:

QFile file = QFile(filepath);

фактически вызывает два конструктора.Может кто-нибудь объяснить?

Ответы [ 5 ]

7 голосов
/ 19 марта 2011
//Java
MyObject o = new MyObject();

//C++
MyObject o = MyObject();

Это , а не эквивалент.Версия c ++ создает новый объект в стеке , что java может делать только с примитивными типами.Как только o выйдет из области видимости, он будет уничтожен.То, что на самом деле происходит выше, логически MyObject o(MyObject()); (неправильный фактический синтаксис) - конструкция, за которой следует конструкция копирования.

MyObject * o = new MyObject();

Это так же близко, как вы добираетесь до своей версии Java.Предостережение, конечно, в том, что в C ++ вам также потребуется delete o; - он не будет собирать мусор.

QFile file = QFile(filepath);

Это создает временный QFile, снова в стеке, а затем создаетfile путем копирования его из временного.Это эквивалентно QFile file(QFile(filepath));.В вашем случае это не будет работать, QFile не позволяет создавать копии, поэтому вам нужно избегать временного, непосредственно создав QFile,

// on stack:
QFile file(filepath);

//or in heap:
QFile * file = new QFile(filepath);
4 голосов
/ 19 марта 2011
MyObject o();

Это не сокращение для любого типа объявления объекта. Это объявление функции с именем o, возвращающей MyObject по значению.

Это самое простое объявление объекта. Если объект имеет объявленный пользователем конструктор, то будет вызван конструктор по умолчанию.

MyObject o;

Для некоторых базовых типов объектов (тех, которые являются или непосредственно содержат POD - plain-old-data - подобъекты и не имеют объявленного пользователем конструктора), некоторые или все объекты можно оставить инициализированными. Чтобы обеспечить инициализацию всех частей такого объекта, вы можете copy-initialize из значения, инициализированного временно. Это не обязательно для объектов, которые имеют объявленный пользователем конструктор.

MyObject o = MyObject();

new требуется только в C ++, где объект должен пережить область, в которой он создан. new всегда возвращает указатель на динамически размещенный объект. В большинстве рабочих кодов обычно следует немедленно назначить такой объект интеллектуальному указателю, например shared_ptr, чтобы гарантировать, что динамически размещенные объекты не будут вытекать.

2 голосов
/ 19 марта 2011

Когда вы объявляете объект следующим образом:

QFile file = QFile(filepath);

Сначала вы вызываете конструктор, который принимает строку (QFile(filepath)), затем вызываете конструктор копирования (QFile(const QFile&)) (через =).

Qt решил сделать конструктор копирования QFile закрытым, чтобы вы не могли его скопировать.

1 голос
/ 19 марта 2011

Да.

QFile file = QFile(filepath);

Создает и создает QFile (тот, что справа от =). Затем вы назначаете это другому QFile. Это вызывает конструктор копирования в QFile, но, как говорится в сообщении об ошибке, он определен как закрытый в QFile, поэтому написанное вами не будет работать.

Что вы, вероятно, хотите сделать, это создать QFile напрямую, как в:

QFile file(filepath);

Между прочим, я думаю, что вы пытаетесь написать C ++ с Java-подобным синтаксисом неправильно! Программисты на C ++, Java или любой другой стране разработали стили написания кода на тех языках, которые по понятным причинам отличаются от других языков. Обычно причина в том, что с помощью этих стилей вы можете написать краткий код, который позволит избежать ошибок и нежелательных побочных эффектов.

1 голос
/ 19 марта 2011
QFile file(filepath);

будет работать нормально, поскольку вызовет конструктор QFile(const QString&).

При выполнении QFile file = x объект file создается с применением конструктора копирования на x, который здесь является приватным, как говорит вам компилятор.

Синтаксис MyClass c(something) это , а не сокращение для MyClass c = something.Второй всегда будет вызывать конструктор копирования, первый вызовет подходящий конструктор в зависимости от типа something.

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