I have two classes Polynom and Fraction.
I need to do a template for Polynom, for using Fraction like coefficient in Polynom, like: 3/4 x^0 + 5\6 x^1 etc.
I understood how to use a simple type like double or int, but how to get this to work for a class I have no idea, and can't find a material on this theme.
class Fraction {
private:
int numerator, denominator;
public:
Fraction();
Fraction(int, int);
Fraction(int);
}
template<class T>
class PolynomT {
private:
int degree;
T *coef;
public:
PolynomT();
explicit PolynomT(int, const T * = nullptr);
~PolynomT();
};
template<class T>
PolynomT<T>::PolynomT(int n, const T *data): degree(n) {
coefA = new T[degree+1];
if (data == nullptr) {
for (int i = 0; i < degree+1; ++i)
coefA[i] = 0.0;
}
else {
for (int i = 0; i < degree + 1; ++i)
coefA[i] = data[i];
}
}
/*Problem here*/
int main() {
PolynomT<Fraction> a(); // what need to pass on here in arguments?
// how should the constructor look like?
/*Example*/
PolynomT<Fraction> b();
PolynomT<Fraction> c = a + b; // or something like this.
}
So, how to do the class constructor for Fraction in PolynomT, and how to do overloading operators for this?
The problem with the coefA[i] = 0.0 assignment in the PolynomT constructor happens because Fraction does not have a constructor that takes a double, nor does it have an assignment operator that takes a double. There are several possible solutions.
Change from raw memory management to std::vector for coefA.
std::vector<T> coefA;
// Then resize appropriately in the constructor
This would automatically fill all the elements with a default constructed object, so you wouldn't need to do anything if data == nullptr.
Another possibility is to change the assignment to
coefA[i] = T();
This will assign a default constructed object of the type (0.0 for doubles).
What are the basic rules and idioms for operator overloading has detailed information on overloading operators.
Related
I'm attempting to implement an overloaded casting operator on my templated array2d class using type T. So I'm to cast from array2d<T> to a new array2d<E>.
I'm able to perform the casting itself but problems arise when I try to set the casted data to the new instance of array2d<E>. The compiler tells me that the casting operator doesn't have access to the private members of array2d
Here's where I am so far (edited out unrelated code for brevity)
array2d.h
template<typename T>
class array2d {
private:
// Member Variables
T** data;
size_t width, height;
public:
// constructors, methods, etc...
// Cast Operator
template<typename E>
operator array2d<E>() const;
};
// Other overloaded operators...
// Overloaded Casting Operator
template<typename T>
template<typename E>
array2d<T>::operator array2d<E>() const{
// Create new instance
array2d<E> castedArr(width, height);
// Allocate memory for the casted data, then cast each element
E** newData = new E*[castedArr.get_height()];
for (size_t i = 0; i < castedArr.get_height(); i++){
newData[i] = new E[castedArr.get_width()];
for (size_t j = 0; j < castedArr.get_width(); j++){
newData[i][j] = (E)data[i][j];
}
}
// issue here, can't set data because it's private.
castedArr.data = newData;
delete [] newData;
newData = nullptr;
return castedArr;
}
main.cpp
#include "array2d.h"
int main(int argc, char *argv[]) {
// Cast Operator
// Create an array2d<T> of
// width = 5
// height = 5
// fill all elements with 42.1
array2d<double> x(5, 5, 42.1);
// Create a new array exactly the same as
// x, where x is casted to int
array2d<int> y = (array2d<int>) x;
return 0;
}
This confused me as I have many other overloaded operators that can access the private members just fine using practically the exact same logic.
Why does this happen and what can I do to rectify it?
When writing a template, you don't nail down the actual type, you create a blue print for different types. array2d<double> and array2d<int> are different types, and by default, two instances of two different classes can't access their private members.
You can fix that by declaring every instantiation of array2d a friend class of the template array2d:
template<typename T>
class array2d {
/* ... */
template<class E> friend class array2d;
/* ... */
};
As a side note, I'm not quite sure wheter
delete [] newData;
is a good idea. You're destroying parts of the resources that the new array2d instance is supposed to manage. If you delete[] that again in array2d::~array2d(), you'll have undefined behavior.
I need some help with operator assignment. This is code:
Sinusoid.h:
class Sinusoid : public Component
{
float fs, f, A, fi;
int N;
double *array;
public:
Sinusoid(float fs, float f, float Ts, float fi, float A);
void count(int type=1);
void clear();
~Sinusoid();
double *getArray() { return this->array; }
double*& operator=(Sinusoid* const &rhs) {
return rhs->array;
};
};
main.cpp:
#include "headers.h"
int main()
{
int N = 1000 * 2.5;
Sinusoid *sinus = new Sinusoid(1000, 15, 2.5, (M_PI / 4), 0.7);
double **answers = new double*[7];
for (int i = 0; i < 7; i++) {
answers[i] = new double[N];
}
//lab1
//Zad1
sinus->count(1);
answers[0] = sinus;
return 0;
}
When i build this code i've got the following problem:
C2440 '=': cannot convert from 'Sinusoid *' to 'double *' main.cpp:15
I know that i can assign two classes with overloaded operator "=" but i want to take a private member of class (double *array;). I know that i can do it by "getArray()" method but i want to learn more "beautiful" practice. Hope you will help me.
Thank you.
Your double*& operator=(Sinusoid* const &rhs) operator doesn't do what you apparently think it does.
An operator= member function allows you to have an instance of the class (Sinusoid) on the left side of an assignment and an instance of the parameter type (Sinusoid*) on the right side. So what you wrote would let you do:
Sinusoid* pointer = whatever;
Sinusoid object;
object = pointer;
Obviously that's not what you intended. (And probably not something you'll ever want.)
The return type of the operator= doesn't have any influence on this fundamental usage. All it means is that the result of object = pointer is then a double*&. So it would let you write:
double* foo;
foo = (object = pointer);
And that's still not helpful for what you want.
Since answers[0] is a pointer, there's no way to create a custom assignment operator for it. However the language has a different mechanism which can be used here. You can create an implicit conversion operator for your class so that compiler is allowed to convert/decay it into a different type when reasonable. Try adding the following to your class:
operator double* () {
return rhs->array;
}
That should work for the case you want.
Although personally I don't think there's anything wrong with leaving the usage to require calling getArray() in the first place. Sometimes the clarity of an explicit function call can make it easier to read what's actually going on.
Try...
class Sinusoid : public Component {
...
operator double*() {
return array;
}
and the usage
answers[0] = *sinus;
I'm implementing matrices according to the strategy pattern.
for that I have MyMatrix, which holds a pointer to Matrix, and two subclasses that inherit from Matrix - SparseMatrix & RegMatrix.
when adding two matrices, because I can't know which matrix I'm adding to which matrix, I implemented a base function which uses an inner method of each inheriting class, and when adding - I just add the new elements to the lefthand matrix.
This works fine.
my problem is - I now want to perform matrix multiplication.
I want to implement this method in the base class - Matrix.
this is what I have until now:
Matrix& multiple(Matrix &other)
{
double result = 0;
int newMatrixRowSize = getRowSize();
int newMatrixColSize = other.getColSize();
double *resultArray = new double[newMatrixRowSize*newMatrixColSize];
for (int i = 1; i <= getColSize(); i++)
{
for (int j = 1; j <= other.getColSize(); j++)
{
for (int k = 1; k <= other.getRowSize(); k++)
{
Pair firstPair(i,k);
Pair secondPair(k,j);
result += getValue(firstPair)*other.getValue(secondPair);
}
Pair resultIndex(i,j);
resultArray[getNumIndex(resultIndex, newMatrixRowSize, newMatrixColSize)] = result;
result = 0;
}
}
delete [] resultArray;
}
only problem is, now I can't just add the new elements to the lefthand matrix, I have to create a new RegMatrix or SparseMatrix, and according to the number of zeros in the matrix - swap to the legit representation of matrix.
so my question is - is it "legal" or good practice to create an instance of the base class' derived class inside the base class?
I want to avoid using the factory pattern, and more willing to do something polymorphic without knowing the kind of matrix in hand
You have to use a factory if you want to create objects of different types depending on condition. If you don't want Matrix to know about its descendants, you have several options. Apart from implementations using interfaces, in C++11 you can use std::function:
class Matrix {
typedef std::function<Matrix*(const double*, int, int)> Factory;
Factory factory;
public:
Matrix(const Factory& f) : factory(f) {}
Matrix* multiple(Matrix &other) {
....
return factory(resultArray, newMatrixRowSize, newMatrixColSize);
}
};
It gives you the advantage that you can pass any function-like object as a factory:
Matrix* matrixFactoryFunc(const double* data, int rowSize, int colSize) {
return nullptr;
}
class MatrixFactoryCallable {
public:
Matrix* operator()(const double* data, int rowSize, int colSize) {
return nullptr;
}
};
class MatrixFactoryWithMemFun {
public:
Matrix* createMatrix(const double* data, int rowSize, int colSize) {
}
};
void testFactory() {
std::function<Matrix*(const double*, int, int)> factory;
factory = matrixFactoryFunc;
factory = MatrixFactoryCallable();
MatrixFactoryWithMemFun mi;
factory = std::bind(&MatrixFactoryWithMemFun::createMatrix, &mi, _1, _2, _3);
Matrix m(factory);
}
I need to modify the ordering of my C++ class members. For example:
class B {
public:
int i;
int j;
int k;
...
};
becomes
class B {
public:
int j;
int k;
int i;
...
};
The problem is there are weird codes in my large code bases that depend on relative location of the class members. For example some functions would assume address of member j is smaller than that of member k.
Is there any CASE tool that can help me to identify any code that read the address of a class member?
I am not aware of any tool that solve your problem, but I would define a class which supports all operators for int type and which overloads ampersand operator so that the result of the operator cannot be casted to a pointer. Then I'd use this class instead of int in your class member definitions and look at places where compiler gives errors.
Something like
class IntWrapper {
public:
IntWrapper() { }
IntWrapper(const int x) { } // don't care about implementation as we
operator int() const { return 0; } // want compile-time errors only
IntWrapper& operator ++() { return *this; }
IntWrapper& operator ++(int) { return *this; }
...
void operator &() const { } // make it void so it would cause compiler error
};
And then:
class B {
public:
IntWrapper i;
IntWrapper j;
IntWrapper k;
...
};
This will not help against using boost::addressof function or some dirty reinterpret_cast of a reference, but addressof is probably never used at all in your project, as well as the reinterpret_cast<char&> trick (who would use it for plain integers?).
You should also care about taking an address of the whole object of B class.
Say I have a class, that wraps some mathematic operation. Lets use a toy example
class Test
{
public:
Test( float f ) : mFloat( f ), mIsInt( false ) {}
float mFloat;
int mInt;
bool mIsFloat;
};
I'd like to create an operator overload with the following prototype:
float operator=( const Test& test )
{
if ( !test.mIsFloat ) return *this; // in this case don't actually do the assignment
return test.mFloat; // in this case do it.
}
So my questions are: can I overload operator= with a built-in return type?
and if so, is there a way to refer to the built-in type?
I know I could do this if I wrapped the built-ins with a class. But in this case I want to have the assignment operator work with built-in types on the LHS
Example of usage:
Test t( 0.5f );
float f = t; // f == 0.5
int i = 0;
i = t; // i stays 0.
UPDATE: Thanks so much for the help. Expanding a little bit from the toy example so people understand what I'm really trying to do.
I have a configuration system that allows me to get config parameters from a tree of parameters with different type ( they can be integers, floats, strings, arrays etc. ).
I can get items from the tree with operations like this:
float updateTime = config["system.updateTime"];
But it is possible that "system.updateTime" does not exist. Or is of the wrong type. Generally for configuration I have a block of defaults, and then code to overide the defaults from the config:
float updateTime = 10;
const char* logFile = "tmp.log";
... etc etc...
I want to do something like:
updateTime = config["system.updateTime"];
Where the operation succeeds if there is an override. So generally the assignment doesn't happen if the return from operator[] is an "invalid" node in the tree.
Right now I solve it with a function like:
getConfig( config, "system.updateTime", updateTime );
But I would prefer to use assignment operator.
I could do this if I were willing to create classes to wrap the builtins.
class MyFloat
{
operator=( const Test& test ) { if (test.isValidNode() ) f = test.float(); return *this; }
float f;
}
But obviously it would be prefereable not to wrap built-ins with trivial classes just to overload assignment. Question is - is this possible in c++?
Based on your example, what you really want is an implicit conversion operator:
class Test
{
// ...
public:
operator float() const;
};
inline Test::operator float() const
{
return mIsFloat ? mFloat : mInt;
}
If you want to conditionally do the assignment, then you need to take another approach. A named method would probably be the best option, all things considered... something like this:
class Test
{
public:
bool try_assign(float & f) const;
};
inline bool Test::try_assign(float & f) const
{
if (mIsFloat) {
f = mFloat;
}
return mIsFloat;
}
Whatever you do, be careful that the syntactic sugar you introduce doesn't result in unreadable code.
You already have one implicit conversion from float to Test, in the form of the convert constructor
class Test
{
public:
/* ... */
Test( float f ) : mFloat( f ) /*...*/ {}
};
Which will support conversions such as:
Test t(0.5f);
You will likely also want a copy-assignement operator in order to make further implicit conversions from float to Test possible:
class Test
{
public:
Test& operator=(float f) { mFloat = f; return *this; }
};
t = 0.75; // This is possible now
In order to support implicit conversion from Test to float you don't use operator=, but a custom cast operator, declared & implemented thusly:
class Test
{
public:
/* ... */
operator float () const { return mFloat; }
};
This makes implicit conversions posslible, such as:
float f = t;
As an aside, you have another implicit conversion happening here you may not even be aware of. In this code:
Test t( 0.5 );
The literal value 0.5 isn't a float, but a double. In order to call the convert constructor this value must be converted to float, which may result in loss of precision. In order to specify a float literal, use the f suffix:
Test t( 0.5f );
Using template specialization:
class Config {
template<typename T>
void setValue(const std::string& index, T& value); //sets the value if available
};
template<float>
void Config::setValue(const std::string& index, float& value){...} //only sets float values
template<int>
void Config::setValue(const std::string& index, int& value){...} //only sets int values;
You can't "overload/add" operators for basic types, but you can for your type Type. But this shall not be operator = but operator >> - like in istreams.
class Test
{
public:
float mFloat;
int mInt;
bool mIsFloat;
Test& operator >> (float& v) { if (mIsFloat) v = mFloat; return *this; }
Test& operator >> (int& v) { if (!mIsFloat) v = mInt; return *this; }
};
Then you can:
int main() {
float v = 2;
Test t = { 1.0, 2, false };
t >> v; // no effect
t.mIsFloat = true;
t >> v; // now v is changed
}
Update
I want to do something like:
updateTime = config["system.updateTime"];
Then with my proposal, you cam:
config["system.updateTime"] >> updateTime;