开发者

c++ Assigning objects in object declaration

I come from a Java background and recently decided to try creating a C++ Qt GUI application "for fun". I've been struggling with many of the finer differences between Java & c++, but I've learned a lot.

I'm attempting to match "java-style" syntax as closely as possible in my C++ coding. While this may or may not be a "best practice" for C++, I feel it helps when learning to keep a familar & consistent syntax. One of the java syntax carryovers is this:

//Java
MyObject o = new MyObject();

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

Now, I understand C++ has a syntax shortcut for the above:

//C++
MyObject o();

This is nice and all, but as I said, I don't want to use different syntax, yet. Everything was working fine, but I received a surprise when I attempted the following Qt code:

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

And got a compile error:

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

I read the Qt docs and discovered that there is in开发者_JAVA技巧deed no public constructor QFile::QFile(const QFile&). Where my code previously worked for other classes, there was such a constructor. I can make a guess here and say that the line:

QFile file = QFile(filepath);

is actually making calls to two constructors. Can someone explain?


//Java
MyObject o = new MyObject();

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

These are not equivalent. The c++ version creates a new object, on stack, something java can only do with primitive types. Once o goes out of scope it will be destructed. What actually happens above is logically MyObject o(MyObject()); (incorrect actual syntax) - construction followed by copy-construction.

MyObject * o = new MyObject();

This is as close as you gets to your java version. The caveat, of course, is that in C++ you'll need to also delete o; - it's not going to get garbage collected.

QFile file = QFile(filepath);

This creates a temporary QFile, again on stack, and then creates file by copy-constructing it from the temporary. It is equivalent to QFile file(QFile(filepath));. In your case this will not work, QFile does not allow copy construction, so you'll need to avoid the temporary by constructing QFile directly,

// on stack:
QFile file(filepath);

//or in heap:
QFile * file = new QFile(filepath);


MyObject o();

This is not a short cut for any type of object declaration. It is a declaration of a function called o returning a MyObject by value.

This is the simplest declaration of an object. If the object has a user-declared constructor then the default constructor will be invoked.

MyObject o;

For some basic object types (those which are or directly contain POD - plain-old-data - subobjects and don't have a user-declared constructor), some or all of the object may be left initialized. To ensure that all parts of such an object are initialized you can copy-initialize from a value initialized temporary. This isn't necessary for objects which do have a user-declared constructor.

MyObject o = MyObject();

new is only require in C++ where an object needs to outlive the scope in which it is created. new always returns a pointer to the dynamically allocated object. In most production code you should normally immediately assign such an object to a smart pointer such as a shared_ptr to ensure that dynamically allocated objects aren't leaked.


When you declare an object like this:

QFile file = QFile(filepath);

You are first calling the constructor that takes a string, (QFile(filepath)), then you are calling the copy constructor (QFile(const QFile&)) (via the =).

Qt decided to make the copy constructor of QFile private, in order to prevent you from copying it.


QFile file(filepath);

will work fine, because it will invoke the QFile(const QString&) constructor.

When doing QFile file = x, the file object is constructed with the copy constructor applied to x, which is private here, as the compiler tells you.

The MyClass c(something) syntax is not a shortcut for MyClass c = something. The second one will always call the copy constructor, the first one will invoke a suitable constructor depending on something's type.


Yes.

QFile file = QFile(filepath);

Creates and constructs a QFile (the one on the right of the =). Then, you assign this to another QFile. This invokes the copy constructor on QFile, but as the error says, that's been defined to be private within QFile, so what you've written won't work.

What you probably want to do is create the QFile directly as in:

QFile file(filepath);

Incidentally, I think you're goal of trying to write C++ with a Java like syntax is misguided! Programmers in C++, Java, or the land of any language have developed styles of writing code in those languages that are different to other languages for good reasons. Usually the reasons are that using those styles you can write concise code that avoid errors and undesired side-effects.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜