5

I have a class B that creates an object of a class A and calls a method of the object.

a.h

#ifndef A_H
#define A_H

class A
{
public:
    A(int);
    void function();
};

#endif // A_H

a.cpp

#include "a.h"

A::A(int x)
{

}
void A::function(){
    //Do something.
}

b.h

#ifndef B_H
#define B_H
#include <QVector>
#include <a.h>


class B
{
public:
    B(int);
    QVector<A> list;
};

#endif // B_H

b.cpp

#include "b.h"

B::B(int y)
{
    list.append(A(y));
    list[0].function();
}  

The problem is that this does not compile. It returns "no matching function to call 'A:A()'". I know that this can be solved with a forward declaration but this does not work here since I want to call the function "function". I also do not want to include the whole class A in the class B.

2
  • 2
    Looks like Qt's asking for a default constructor. Commented Jan 14, 2019 at 12:08
  • 2
    your interpretation is not quite correct. "no matching function to call 'A:A()'" means that A has no default constructor, but you are trying to call it Commented Jan 14, 2019 at 12:08

2 Answers 2

11

As with many Qt containers, QVector's element type must be an assignable data type in your version.

Unlike the standard library, Qt defines this as:

The values stored in the various containers can be of any assignable data type. To qualify, a type must provide a default constructor, a copy constructor, and an assignment operator.

This is really unfortunate, because there's no practical need for a default constructor in your example, and indeed a std::vector would (compliantly) let you use an element type that doesn't have one.

The QVector::value(int) function does rely on this property, but you're not using it! The Qt devs must be doing some kind of checks up-front, rather than taking the standard library's approach of "just check preconditions when they're actually needed", or else this is an "accident" of the code!

As a consequence, until 5.13 in which this was changed, you will have to give A a default constructor, sorry.

Don't forget a copy constructor, too… and a proper qualification on that A::function() definition.

A forward declaration will not solve this, neither do you need one. In fact, adding one to this particular program will do literally nothing. ;)

Sign up to request clarification or add additional context in comments.

5 Comments

The alternative solution is to switch to std::vector of course.
Good News Everyone! The requirement of a default constructor for QVector has been finally dropped in 5.13 (commit).
The Qt devs must be doing some kind of checks up-front, rather than taking the standard library's approach of "just check preconditions when they're actually needed". It's worse... it's just sloppy coding, e.g. calling resize() from insertion functions or stuff like that :-(
@peppe: Possibly. Possibly not. (Ignore if you literally know otherwise from the source!)
Gory details: in 5.12 detach() (called by any non-const function, e.g. insertion functions) calls into reallocData(), which is a one-size-fits-all function that does detaching, allocation, resizing, reserving, and so on. The result is the imposed requirement. Other functions are also sloppy coded (e.g. clear() in 5.12 calls resize(0)).
0

First in a.cpp update function definition:

void A::function(){  // A: added
    //Do something.
}

Second, I would add A(const A&) copy constructor since list may need this for internal buffer reallocation purposes.

1 Comment

While you're right that the function definition is currently broken, and that a copy constructor should be added, none of this answers the question, which is about why a default-constructor is being invoked and how best to resolve that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.