That's because your class is designed to multiply a CMatrix with a Matrix, or add a CVector to a Vector, which isn't right. What you want is to be able to multiply a CMatrix with a CMatrix, or add a CVector with a CVector (and obtain a CMatrix or CVector in return respectively). Then only these multiplication/addition functions have to mess with the "v" and "m" fields, and you can safely make these fields private, as they should be.

It seems to me you've complicated your math library for no reason, by adding an extra composition layer between the raw data (Matrix, a structure of 16 floats) and the class that manipulates this data (CMatrix, which interprets it and adds/multiplies/etc..). Typically this wouldn't be "bad" (even though it is usually done internally, and the raw data structure (Matrix) is never exposed outside of its wrapper class (CMatrix) except through serialization/deserialization, if applicable) but in your case it is problematic because your class asks for the raw data to operate on, and hence cannot directly operate on itself, which makes it impossible to handle matrices through CMatrix alone - you have to constantly bounce back and forth between the data (by accessing the "m" field) and the class that operates on matrices (by calling a function that takes this field as a parameter).

If that's not clear enough, what you've basically written is a class that doesn't really contain anything. Up to a few details, all of the useful functions in CMatrix could be made static (or free functions) and the code reduced to moving Matrix variables around and calling CMatrix static functions on them, which is essentially what you are doing now, even if it somewhat obfuscated. You need to decide on whether you want CMatrix to simply contain functions that work on Matrix variables and not actually hold a matrix themselves, or whether you want CMatrix to represent an individual matrix equipped with functions that can operate on it and other matrices (the second approach is the more popular one). Again, both can be made to work, but in your case your code seems to exist somewhere between the two approaches, and as a result is encountering severe design and consistency problems. Once you've decided on what you want your class to actually do, you should know what to modify.

The same goes for CVector and so on, naturally.

The slowsort algorithm is a perfect illustration of the multiply and surrender paradigm, which is perhaps the single most important paradigm in the development of reluctant algorithms. The basic multiply and surrender strategy consists in replacing the problem at hand by two or more subproblems, each slightly simpler than the original, and continue multiplying subproblems and subsubproblems recursively in this fashion as long as possible. At some point the subproblems will all become so simple that their solution can no longer be postponed, and we will have to surrender. Experience shows that, in most cases, by the time this point is reached the total work will be substantially higher than what could have been wasted by a more direct approach.

- *Pessimal Algorithms and Simplexity Analysis*