5

I am new to C++ and recently took on the study of objective oriented programming. I wanted to write my own linear algebra module processing three dimensional vectors and 3x3 matrices. I tried to define a matrix as a class consisting of three vectors.

class vector {
  public:
  double n1, n2, n3;
  vector (double a, double b, double c) {
         n1 = a; n2 = b; n3 = c;
         }
  };

class matrix {
  public:
         vector m1, m2, m3;
         matrix (vector a, vector b, vector c) {
                m1 = a; m2 = b; m3 = c;
                }
         };

However, I am getting a compilation error:

In constructor `matrix::matrix(vector, vector, vector)':
no matching function for call to `vector::vector()'

I am guessing that the program doesnt know how to construct a matrix using the vector class i defined. However I do not understand why. If anybody could explain, i would be very grateful.

audio
  • 314
  • 4
  • 12
  • 1
    Use the initializer list instead of assigning them in the constructor body. – James M Aug 29 '13 at 11:43
  • possible duplicate of [What is this weird colon-member syntax in the constructor?](http://stackoverflow.com/questions/1711990/what-is-this-weird-colon-member-syntax-in-the-constructor) – Alok Save Aug 29 '13 at 11:46
  • 2
    you might want to put your vector class inside a namespace to prevent confusion with `std::vector`. Because when I read your matrix class I was seriously thinking you intended to use `std::vector`, but thats not the case. – hetepeperfan Aug 29 '13 at 11:55

5 Answers5

6

You need to initialize your m1,m2,m3 members by member initializer list:

matrix (const vector& a, const vector& b, const vector& c)
: m1(a),m2(b),m3(c)

Note the following:

  • This form can be used only with constructors.
  • You must (at least, in pre-C++11) use this form to initialize a nonstatic const data member.
  • You must use this form to initialize a reference data member.

Also, note, there is std::vector, you may want to rename your own vector to void naming confliction and you'd better pass vector by const reference.

billz
  • 44,644
  • 9
  • 83
  • 100
4

Here's why this is going wrong:

Construction of an object happens in multiple phases. For your matrix class, you first need to construct all member objects and only then execute the constructor body. The important thing to realize here is that before the constructor body is entered, all member objects (in your case m1, m2 and m3) must have been constructed.

The problem is that the compiler cannot construct the vector members by itself: It only knows one constructor for vector and that one requires three doubles for construction, which it does not have. You can provide the compiler with those missing constructor arguments for vector using the initializer list syntax, as suggested by billz's answer.

This works because the initializer list is executed during the member-construction phase of startup, which happens before the constructor-body phase.

Alternatively, provide a default constructor for vector so that the compiler is able to automatically construct the matrix members without additional information, as suggested by Zac's answer.

ComicSansMS
  • 51,484
  • 14
  • 155
  • 166
1

It is needed the default constructor of class vector, the one with no parameters:

class vector {
  public:
  double n1, n2, n3;
  vector () { // <- this one
    n1 = 0; n2 = -1; // sample initializing code
  };
  vector (double a, double b, double c) {
         n1 = a; n2 = b; n3 = c;
         }
  };
Zac
  • 4,510
  • 3
  • 36
  • 44
0

The reason why you got this error is that:

  1. Your vector class has no default constructor as you have defined one explicit constructor with parameters.
  2. The data member of one object will be initialized during object construction but before the code in constructor is executed.

So when compiler wants to create matrix object, it needs to first construct/initialize m1/m2/m3 befor these codes "{ m1 = a; m2 = b; m3 = c;}" of matrix constructor. However, the class of m1/m2/m3 has no default constructor to be called. This is why compiler reports "In constructor matrix::matrix(vector, vector, vector)': no matching function for call tovector::vector()'"

The solution is to initialize the m1/m2/m3 through member initialization list. This works because:

  1. The compiler will provide "default copy constructor" (actually just bit-wise copy for your case) when it is not defined.
  2. This "default copy constructor" could be called through member initialization list.
JackyZhu
  • 394
  • 3
  • 10
0

Or with the "recommended c++11" way:

matrix (vector a, vector b, vector c)
: m1(std::move(a)),m2(std::move(b)),m3(std::move(c)) {
}
Fredrik Jansson
  • 3,764
  • 3
  • 30
  • 33