I understand why I get a C2248: 'QObject::QObject' : cannot access private member declared in class 'QObject' . Qt objects are not copyable, as explained here:
https://stackoverflow.com/a/3513395/356726
No copy constructor or assignment operator
The problem is, that the compiler message always indicates the last line (closing }) of the class:
class MyQObject : public QObject {
Q_OBJECT
....
}; <-- error line
Root cause is somewhere else, ie. where the class is copied (other file, some different line in code). This is sometimes hard to spot!
Question: Is there a way to locate the line of the real reason for the error
Remark: Please note, before you mark this Duplicate. Question is about finding the root cause, not how to solve it as in the other questions.
--- Edit 1 ---
Good hint Kuba et.al. It's VS2010, compiling in Qt Creator 2.8.0
'QObject::QObject'
C:\Qt\5.1.0-32\qtbase\include\QtCore/qobject.h(115) : see declaration of 'QObject'
This diagnostic occurred in the compiler generated function 'MyQObject ::MyQObject (const MyQObject &)'
I wonder why a copy constructor is generated. One idea crossed my mind, I am using the DBus enabled version of Qt, might this be the reason?
The easiest solution to detect the root cause is by making your copy ctor also private. (Or deleted, but that's not possible in VS2010 yet). This will suppress the automatically-generated copy ctor, which was the source of the error.
If you are not explicitly copying your MyObject but you keep getting this error message then something you're using in conjunction with your MyObject is doing the copying on your behalf.
The most likely culprit would be one of the container classes, e.g. QList, QVector, etc.
Read the Container class documentation for more information as well as the specific class' documentation of any container you might be using. All containers have requirements of their elements, e.g. Must have default constructor, must be assignable, etc. This is where I think your problem lies.
Related
My class's constructor opens a file and reads some data from it. The constructor does not take any argument.
The file opening part has to be done inside the constructor.
What is the way to test the conditions inside such a constructor with gtest?
Quick answer is: there is noway given the information you provided.
If however the file handle you opened, or any related flag/variable, is protected, one technique with gtest is to inherit from your class and use the derived class to access that data, and test it.
As a side note, constructors should not do stuffs: in your example, imagine that for any reason the filesystem does not allow you to open the file. How does this affect the class behavior? You cannot state. Therefore you may have undefined behavior from your class and you do not have any control on it.
Even worse is the throw exception suggestion, for the same reason. Use dependency injection in your constructor or make your class a template class in such a way that you can control the injected policy.
I'm reading this Qt doc page about custom types, and it states the following:
The default constructor, copy constructor and destructor are all required, and must be public, if the type is to be integrated into the meta-object system.
Suppose I have an object that needs to be built with some required parameters, because it has no sense to be built using the default constructor, for example:
struct IntPair
{
IntPair(int first, int second);
~IntPair();
};
To make it available in the Qt Meta Object system, as the doc states, it requires the default constructor. But practically, it has no sense to give the opportunity to build an IntPair object without a pair of integer numbers (sorry for the ugly example).
Is there a way to achieve this without implementing the default constructor? I'm thinking about a sort of friendship between my object and the Qt Meta Object system...
Basically, I cannot understand why the default constructor is needed.
There are two parts to the question:
Achieving a custom Meta Object without implementing a default ctor.
Understanding why a default ctor is required by Qt in this case.
Other respondents have addressed (2) already.
I wish to address (1).
I wrote a class, and I intend for users of this class to call a ctor I wrote which requires several arguments. However, because of the Qt-related requirements, I am forced to add a zero-argument constructor.
It would make me happy to at least make the zero-arg ctor private, so that I could enforce that all user code EXCEPT moc-generated "magic" code will be barred from using that ctor.
Hello, happiness! It is possible.
You can indeed use friendship to make the default ctor private and still use Qt Metatype.
It looks something like this:
class MyClass {
Q_GADGET
Q_PROPERTY(QString text READ text)
public:
MyClass(QString text, bool sometruth, int someint);
QString text() const { return text_; }
private:
// Works in my project using Qt 5.12. (see hints below if it fails for you)
friend struct QtMetaTypePrivate::QMetaTypeFunctionHelper<MyClass, true>;
// Prefer the ctor that takes arguments. This ctor only exists to satisfy Qt.
MyClass();
QString text_;
};
There are two ways you can solve the problem of figuring out WHAT to befriend.
You can mark the ctor private, try to recompile, and scrutinize the compiler error to figure out what other type is trying to access the ctor of your class.
Or, you can put an assert(false); in the body of your ctor, create a binary with debug symbols (including Qt debug symbols), then look at the stack in the debugger when the assertion fails. The stack will show the Qt-internal member-function or free function that called into your ctor. Friend whatever that caller is.
This last method (using the debugger) is what worked for me. (I wasn't fluent enough in compiler-ese to discern which type from the output of the gigantic compiler error was what I needed to add as my friend.)
It has to do with QVariant's (templated) implementation.
Look at qvariant.h in the QT5.5 source code tree, and you'll find this:
T t;
if (v.convert(vid, &t))
return t;
return T();
And also:
old->~T();
new (old) T(t); //call the copy constructor
Hence the need for a public constructor/desctructor, and copy-constructor.
The advantage of all of this is being able to use your custom type in signals/slots (and other meta-object magic), but there are drawbacks like in your situation. It's just a trade-off that you have to live with.
As a workaround, you could have some sort of "init()" method that actually initializes the object after it's constructed. Not as safe/elegant, but it works.
As to why, there's a design reason behind it. It involves a "Identity vs Value" discussion that I think is too long to paste here.
As to how, #AlexanderVX commented on using default values in arguments.
Custom data type should have public default constructors because many parts of the Qt framework will call it to avoid returning null pointers. E.g. QVariant and containers accessors (e.g. QHash::value()).
In your case IntPair() : IntPair(0,0) { } should be nice, isn't it ?
In many cases it is convenient to hold data in objects impementing Qt's implicit sharing pattern (see http://doc.qt.io/qt-5/implicit-sharing.html), in which case the default constructor may easily initialize with QSharedDataPointer(0) and every accessor return a default value when pointer is null (e.g. 0 for an int, QString() for a QString, etc.), guess what: every accessor will be able to provide a default value by calling the public default constructor of the data type because it is required to have one :-).
I have need of a simple hash table in my project and from the documentation it seems like CMapStringToString is exactly what I want. However, I've found that simply adding a new field to my class is sufficient to throw an error message, even if I'm not otherwise accessing it.
... other class members
CMapStringToString myMap;
Just doing this gives me this error:
...
error C2248: 'CObject::CObject' : cannot access private member declared in
class 'CObject'
Nowhere is anything referencing myMap as yet.
The file & line number for the error is "afxcoll.h" at line 1503, which is the closing brace of the CMapStringToString class definition.
Does anybody know what the problem is here? Is there sample code for this class anywhere?
Someone had earlier posted an answer suggesting the problem was that the copy constructor was private and suggested creating my own copy constructor for the class with the map. This does not work, and whomever posted it actually deleted their own answer (after I'd read it but before I'd responded).
I ended up creating a class derived from CMapStringToString and wrote a copy constructor for it. This wasn't quite the same thing as the earlier suggestion and it worked. Thanks to all for your suggestions. They may not have been exactly right but they at least steered me in the right direction.
Maybe your class doesn't have a copy constructor and you're trying to copy an instance somewhere? Most of the time this wouldn't yield an error, but since the underlying type of the CMapStringToString class is Object it might be needed.
How to get around error
C4150: deletion of pointer to incomplete type COldStuff; no destructor called
without adding the header. E.g.
class COldStuff;
class CSomething
{
...
CAnother<COldStuff> m_test;
}
I am using legacy code for all this (ie COldStuff, CAnother, CSomething). When I add the header to fix c4150, I run into circular dependency and especially redefinition problems. How else can I get around this problem; if I cannot turn off treat warning as error, or ignore this, or change the legacy code.... Can I somehow let the compiler know COldStuff's destructor or that COldStuff does have a destructor?
Potential fix: Explicitly define the destructor for CSomething in your source file (even if it's just empty).
Why this probably works: From the comments and Rup's excellent question, I assume that CAnother tries to delete COldStuff, at which point it has to be visible. Now if you do not explicitly define a destructor for CSomething, that part is instantiated inline too (basically in the header, giving you the error). However, if you explicitly define a destructor in the cpp file of CSomething, the implicit CAnother<COldStuff>::~CAnother is instantiated there and you can resolve the circular dependency.
Oh, that's bad.
Maybe you could introduce a base class with a virtual destructor, and delete that way. But you can't cast an incomplete type to its base class, nor can you call a member function which would know how to delete it properly.
I think ultimately whatever you pass these COldStuff objects to that knows how to use them, also needs to be responsible for deleting them.
At least some small changes to the legacy code will be necessary to fix this.
This isn't something you can get away with. When deleting an object, the compiler has to see the complete type. What if it has a destructor?
The usual fix is to put the delete in a cpp file where the complete type is visible. might be hard if the deleter is a template, but perhaps you can use a small helper function.
Replace forward declaration of COldStuff by including its header file.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What's the most reliable way to prohibit a copy constructor in C++?
Suppose I want to make a class non-copyable and want to prohibit copy constructor and assignment operator. I make them private and leave unimplemented:
class Class {
//useful stuff, then
private:
Class( const Class& ); //not implemented anywhere
void operator=( const Class& ); //not implemented anywhere
};
this way if any of them is accidentially called from within friends or the same class I get a link-time error.
Now what if a user implements them? I mean there's no implementation, so anyone can add his own:
Class::Class( const Class& )
{
//whatever they want
}
Of course I could have created my own implementation and add an assertion there, but that would delay unintended calls detection until the program is run.
Is there a way to prevent implementing such method by a user and still have compile-time detection of unintended calls to them?
In C++0x there is the new delete keyword, that does just this
What's the most reliable way to prohibit a copy constructor in C++?
There is no problem here.
The client can provide implementations of those methods a much as they like, but the compiler will still complain because they're private.
Now, can you prevent someone hacking your header file, changing them to public and linking their own implementations?
Yes, provide your own implementations that throw exceptions, your hypothetical hacker will get a link error when they try to build.
In the normal course of events this doesn't slow anything down, as the compiler will never try to call those methods, and code that tries will be told
. . . cannot access private member
declared in class . . .
In the case some "clever" gobshite tries, then yes the assertions will be delayed, but mate, that's not your problem, you can't protect every idiot in the world from shooting them selves in the foot.
+1 BTW, interesting question :)
. . . as pointed out by Xeo, the above only works for non templated classes
Well the solution is like it is usually done in practice - use special non-copyable base class (e.g. boost::noncopyable or your own class). E.g.
class noncopyable
{
// private
noncopyable( const noncopyable& ); // not implemented
noncopyable& operator=( const noncopyable& ); // not implemented
// no friends, etc
};
Then somewhere
class A: noncopyable
{
// Anything ...
};
Obviously since there is no friends of noncopyable its copy constuctor and assignment operator is always private for everyone so it doesn't matter if it is implemented or not (compiler denies using them anyway).
A bit of a non-answer to the question, but perhaps a different approach, depending a lot on what you're trying to achieve.
On the face of it, it sounds like you want compile time detection whilst you're developing the library in order to speed up detection and avoid relying on runtime testing identifying the issue.
If this is the case, can you not solve your problem by having two builds?
Build One (internal build): which builds the library and doesn't link in the copy constructor functions.
Build Two (client build): which links in the copy construction logic with asserts (from a different implementation file), so that there's runtime protection & the client can't provide their own implementation.
WHat you want to do is called MUTUAL exclusion....
the best way to do what you want is...
MAKE ANOTHER CLASS THAT IMPLEMENTS THERE FUNCTIONS>>>>
and make an object of that class in your class.....that way you can access the function BUT NO ONE CAN else can really get into them since they dont exist in the class.... :) hope this answers your question