Say I have two classes, One and Two. One and Two are essentially the same, but Two can convert into One.
#ifndef _ONE_H_
#define _ONE_H_
class One
{
private:
float m_x;
float m_y;
public:
One();
One(float x, float y);
};
#endif
#ifndef _TWO_H_
#define _TWO_H_
#include "One.h"
class Two
{
private:
float m_x;
float m_y;
public:
Two();
Two(float x, float y);
operator One() { return One(m_x, m_y); }
operator One* () { return &One(m_x, m_y); }
operator One& () const { return *this; }
float GetX(void) { return m_x ;}
float GetY(void) { return m_y ;}
void Print();
};
#endif
Two has access to One, but One does not have access to Two. In the main.cpp I have:
One a(4.5f, 5.5f);
Two b(10.5, 7.5);
One * c = &b;
I get an error if I try to do the pointer of a One to the address of a Two. The error is "error C2440: 'initializing' : cannot convert from 'Two *' to 'One *'"
I cannot for the life of me figure out how to do this, if it is even possible. Any help would be appreciated.
EDIT: Added a new line to Two.h with operator One& () const { return *this; }. The function I'm attempting to use to get this conversion operator to work is void TestRefConstPrint(const One &testClass); With main below, this presents a new error for "cannot convert parameter 1 from Two' to 'const One &'.
Inside main I do:
int main()
{
Two b(10.5, 7.5);
TestRefConstPrint(b);
return 0;
}
Your conversion operators enable the conversions Two -> One and Two -> One*. You are trying to perform a different conversion, Two* -> One*.
To use your operator One() conversion operator to perform a Two -> One conversion, just do this:
One c = b;
If you really want to do a Two* -> One* conversion, you can, with an explicit cast:
One * c = (One *)&b;
or using C++-style casts:
One * c = reinterpret_cast<One *>(&b);
Note, however, that this does not use either of your conversion operators, and does a very different thing from the Two -> One conversion: it does not create a new object, it makes a pointer-to-One that points to the memory occupied by a Two object. This is generally a bad idea, and it's unlikely that you want to do this.
Finally, a comment about your operator One*(): it returns a dangling pointer (a pointer to a local variable which goes out of scope when the function returns). I assume you wrote it in your attempt to get the Two* -> One* conversion to work. You should remove it because it does not do what you want.
Related
I'm fairly new to C++. I've searched extensively but I couldn't make it work.
I've defined a custom type called vec_t:
class FloatType {
private:
float value;
public:
FloatType() : value(0.0f) {}
FloatType(float v) : value(v) {}
//operator float() { return value; }
//operator float() { return value; }
//explicit operator const float* () { return &value; }
//operator float* () const { return &value; }
//operator const float* () { return &value; }
//operator const float() { return (const float)value; }
//operator const float*() { return &value; }
};
typedef FloatType vec_t;
I've also created a function which takes a const float * as its only argument:
void Create(const float* vColor = NULL);
void Create(const float* vColor) {
//...
}
Now, when calling the function like so:
vec_t a = { 2.5f };
vec_t* b = &a;
Create(b);
Visual Studio Community 2019 (v142) is complaining:
argument of type "vec_t *" is incompatible with parameter of type "const float *"
Now, casting it to const float * on the spot gets it done:
Create((const float *)b);
But, my goal is to have an implicit casting operator to implicitly convert from my type to const float *, but no matter my efforts, I can not seem to have it right.
All operator comments were my attempts and they all have valid syntax, but they don't make the problem go away.
What am I not understanding?
I want to be able to handle this from within the FloatType class itself, and to my knowledge, an implicit casting operator is the way to do so.
Don't guide me to another approach, this is purely for practice and exercise.
The problem is that while vec_t is a class type that can have conversion operators defined, vec_t * is a primitive type (a pointer), and no user-defined conversions apply to it.
Some possible solutions:
Don't pass around pointers to vec_t, pass them by value instead. If necessary, use std::move to avoid potentially expensive copies. This boils down to just Create(a). john's answer explains this in more detail.
Dereference the pointer, as in Create(*b), to allow the compiler to find your user-defined conversions.
Add a float * data() member function to vec_t, just like std::vector, and call that to get at the underlying data: Create(b->data())
Don't use your own vector type and just use std::array<float, N> for statically-sized vectors and std::vector<float> for dynamically sized ones. This is likely the best solution. To get a pointer to the raw data, use vec.data(). (Again, take advantage of these types' value semantics to get memory safety. Move / copy them, don't use raw pointers.)
If you want something really ugly that you shouldn't do: Create(b->operator float *()).
Your vec_t type is not a pointer, so you should not be using a pointer as the argument when calling Create():
class FloatType
{
private:
float value;
public:
...
operator const float* () const { return &value; }
// const here ^^^^^
};
typedef FloatType vec_t;
vec_t a = { 2.5f };
Create(a);
For some reason, you introduced the pointer b, that's the main reason your code doesn't work.
Also, you should have an extra const on your conversion operator, as I've indicated above.
I want to add 2 objects, by overloading the + operator, but my compiler says there's no matching function to call to point::point(int, int). Can somebody please help me with this code, and explain the error ? thank you
#include <iostream>
using namespace std;
class point{
int x,y;
public:
point operator+ (point & first, point & second)
{
return point (first.x + second.x,first.y + second.y);
}
};
int main()
{
point lf (1,3)
point ls (4,5)
point el = lf + ls;
return 0;
}
You can just change your code like this,
#include <iostream>
using namespace std;
class point {
int x, y;
public:
point(int i, int j)
{
x = i;
y = j;
}
point operator+ (const point & first) const
{
return point(x + first.x, y + first.y);
}
};
int main()
{
point lf(1, 3);
point ls(4, 5);
point el = lf + ls;
return 0;
}
Hope this helps...
class point{
int x,y;
public:
point& operator+=(point const& rhs)& {
x+=rhs.x;
y+=rhs.y;
return *this;
}
friend point operator+(point lhs, point const& rhs){
lhs+=rhs;
return lhs;
}
};
There are a pile of little tricks above that make following this pattern a good "no brainer".
You get both += and + with the "proper" semantics.
If you chain +s together, you get elision of the left hand side operation. (ie, a+b+c becomes (a+b)+c, the return value of a+b is elided into the _+c call). If your objects have movable state, the proper moves happen for no design cost.
a+b works if either a or b is a point, and the other has an implicit-conversion-to-point. Member operator+ does not do this if a is not a point; this is pointless asymmetry.
a+=b is often more efficient to implement than a=a+b. When you implement += here, you get an efficient + as well. And your += is in turn defined in terms of member variable +=s.
The error with gdb I get is
main.cpp:8:49: error: ‘point point::operator+(point&, point&)’ must take either zero or one argument
This is because the the object that you plan to perform the operation on is this (the left hand side) and then the right hand side is the argument. If you wish to use the format that you've taken, then you can put the declaration outside the class - ie
struct point
{
// note made into a struct to ensure that the below operator can access the variables.
// alternatively one could make the function a friend if that's your preference
int x,y;
};
point operator+ (const point & first, const point & second) {
// note these {} are c++11 onwards. if you don't use c++11 then
// feel free to provide your own constructor.
return point {first.x + second.x,first.y + second.y};
}
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;
the question may look silly ,but i want to ask..
Is there any way we can declare a method in a class with same signature but different return type (like int fun(int) and float fun(int) ) and during the object creation can we dynamically decide which function to be executed! i have got the compilation error...is there any other way to achieve this logic may be using templates...
You can always take the return value as a template.
template<typename T> T fun(int);
template<> float fun<float>(int);
template<> int fun<int>(int);
Can you decide dynamically at run-time which to call? No.
#DeadMG proposed the template based solution, however you can simply "tweak" the signature (which is, arguably, what the template argument does).
The idea is simply to add a dummy argument:
struct Foo
{
float fun(float); // no name, it's a dummy
int fun(int); // no name, it's a dummy
};
Then for execution:
int main() {
Foo foo;
std::cout << foo.fun(int()) << ", " << foo.fun(float());
}
This can be used exactly as the template solution (ie invoked from a template method), but is much easier to pull:
less wordy
function template specialization should be defined outside the class (although VC++ will accept inline definition in the class)
I prefer to avoid function template specialization, in general, as with specialization on arguments, the rules for selecting the right overload/specialization are tricky.
You can (but shouldn't*) use a proxy class that overloads the conversion operators.
Long example with actual usecase *
Let me take my example from Dot & Cross Product Notation:
[...]
There is also the possibility of having operator* for both dot-product and cross-product.
Assume a basic vector-type (just for demonstration):
struct Vector {
float x,y,z;
Vector() {}
Vector (float x, float y, float z) : x(x), y(y), z(z) {}
};
We observe that the dot-product is a scalar, the cross-product is a vector. In C++, we may overload conversion operators:
struct VecMulRet {
public:
operator Vector () const {
return Vector (
lhs.y*rhs.z - lhs.z*rhs.y,
lhs.z*rhs.x - lhs.x*rhs.z,
lhs.x*rhs.y - lhs.y*rhs.x
);
}
operator float () const {
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
}
private:
// make construction private and only allow operator* to create an instance
Vector const lhs, rhs;
VecMulRet (Vector const &lhs, Vector const &rhs)
: lhs(lhs), rhs(rhs)
{}
friend VecMulRet operator * (Vector const &lhs, Vector const &rhs);
};
Only operator* is allowed to use struct VecMulRet, copying of VecMulRet is forbidden (paranoia first).
Operator* is now defined as follows:
VecMulRet operator * (Vector const &lhs, Vector const &rhs) {
return VecMulRet (lhs, rhs);
}
Et voila, we can write:
int main () {
Vector a,b;
float dot = a*b;
Vector cross = a*b;
}
Btw, this is blessed by the Holy Standard as established in 1999.
If you read further in that thread, you'll find a benchmark that confirms that this comes at no performance penalty.
Short example for demonstration *
If that was too much to grasp, a more constructed example:
struct my_multi_ret {
operator unsigned int() const { return 0xdeadbeef; }
operator float() const { return 42.f; }
};
my_multi_ret multi () {
return my_multi_ret();
}
#include <iostream>
#include <iomanip>
int main () {
unsigned int i = multi();
float f = multi();
std::cout << std::hex << i << ", " << f << std::endl;
}
* You can, but shouldn't, because it does not conform to the principle of least surprise as it is not common practice. Still, it is funny.
What I'm trying to do is create a new custom data type that behaves like all other primitive types. Specifically, this data type appears like a Fixed Point fraction.
I've created a class to represent this data type, called "class FixedPoint", and in it there are ways to typecast from "FixedPoint" to "int" or "double" or "unsigned int", etc. That is fine.
Now, what if I want to cast from "int" to "FixedPoint"? Originally my solution was to have a constructor:
FixedPoint(int i) { /* some conversion from 'int' to 'FixedPoint' in here */ }
This works...but you cannot put it into a union like so:
union {
FixedPoint p;
};
This will break, because "FixedPoint" does not have an implicit trivial constructor (we just defined a constructor, "FixedPoint(int i)").
To summarize, the whole issue is "we want to cast from some type T to type FixedPoint without explicitly defining a constructor so we can use our type FixedPoint in a union".
What I think the solution is but cannot find any evidence online:
Define an overloaded global typecast operator to cast from "int" to "FixedPoint".
Is there a way to do this without using class constructors? I'd like to be able to use this class in a union. What I've tried (in global scope):
operator (FixedPoint f, int a) { ... } //compiler complains about this is not a method or non-static.
And a little example to show unions don't like constructors (they like POD)
class bob
{
public:
bob(int a) { m_num = a; }
private:
int m_num;
};
void duck()
{
union
{
bob a;
};
}
This error seen in Visual Studio is:
error C2620: member 'duck::<unnamed-tag>::a' of union 'duck::<unnamed-tag>' has user-defined constructor or non-trivial default constructor
Any ideas?
Thanks
I am having a hard time at seeing what you would try to use this for. It seems smelly to have to constantly ensure that sizeof(FixedPoint) == sizeof(int) and, assuming that, there are other hidden gotchas, like endianness. Maybe I should back up a little bit here, unions only "convert" a value from one type to another in that it takes a chunk of memory and references it as a different type. i.e.
union BadConverter
{
int integer;
double fraction;
};
BadConverter.fraction = 100.0/33.0;
BadConverter.integer = ?;
I am pretty sure integer is not going to be 3, it is going to whatever the memory chunk of the double is that the integer bytes share with it.
Unions don't seem to be a very good fit for this sort of thing. I would think just defining a bunch of assignment operators from all the primitive types. i.e.
class FixedPoint
{
FixedPoint& operator=(int value);
FixedPoint& operator=(double value);
..etc..
//Maybe something like this?
template<typename T>
FixedPoint& operator=(const T& value)
{
value = boost::lexical_cast<int>(value);
return *this;
}
}
Custom conversion operators must be a member of the class that is being converted from. A non-trivial constructor is not required.
EDIT: I reworked the example to utilize a union since this is what you were asking about.
EDIT2: See below if you are trying to go the other way (construction) and don't want constructors.
#include <string>
#include <sstream>
using namespace std;
class FixedPoint
{
public:
operator std::string() const
{
stringstream ss;
ss << x_ << ", " << y_;
return ss.str();
}
int x_, y_;
};
union Items
{
FixedPoint point_;
int val_;
};
int main()
{
Items i;
i.point_.x_ = 42;
i.point_.y_ = 84;
string s = i.point_;
}
If you're trying to go the other way -- eg, from an int to FixedPoint in my example -- then the normal way to do this is indeed to use a conversion constructor. Given that you don't want a non-trivial constructor, you have to resort to a conversion function.
FixedPoint make_fixed_point(int x, int y)
{
FixedPoint ret;
ret.x_ = x;
ret.y_ = y;
return ret;
}
union Items
{
FixedPoint point_;
int val_;
};
int main()
{
Items i;
i.point_ = make_fixed_point(111,222);
}
Can't you just add a default constructor that'll allow it to be part of the union.
For example:
class bob
{
public:
bob(int a=0) { m_num = a; }
private:
int m_num;
};
void duck()
{
union
{
bob a;
};
}
By giving the a=0 default, it should be able to be put in a union. I didn't try it myself, though.