I have the folllowing interface:
class A
{
public:
virtual A * operator+(const A &rhs) const = 0;
}
And the abstract class :
class B : public A
{
public:
B(int val)
{
this->val = val;
}
virtual A * operator+(const A &rhs) const
{
return (new B(this->val + rhs.val));
}
int val;
}
Moreover, I have this class :
class C
{
public:
void add();
private:
std::stack<A *> Astack;
}
The operator+ prototype cannot be modified.
My issue is that I fails to create the add function. I tried this:
void C::add()
{
B first = *dynamic_cast<B *>(this->Astack.top()); // Error here
this->Astack.pop();
B second = *dynamic_cast<B *>(this->Astack.top()); // And here
this->Astack.pop();
B * res = first + second;
this->Astack.push(res);
}
But my compiler tells me :
error: cannot convert B to A * in initialization.
In fact, I fails to obtain to B to add them.
Operators cannot be virtual (well, technically they can, but it's a recipe for disaster, causing slicing, weird arithmetic expressions in client code and the unwarranted murder of cute baby seals).
Your C::add should look similar to this:
void C::add() // assuming implementation is supposed to sum instances and
// add replace the contents of Astack with the sum
{
A* x = Astack.top();
Astack.pop();
while(!Astack.empty()) {
A* y = Astack.top();
Astack.pop();
A* z = (*x) + (*y);
delete x;
delete y;
x = z; // latest result will be in x on the next iteration
}
Astack.push(x);
}
Also, your teacher should learn about not abusing memory allocation, not abusing virtual functions, not imposing virtual operators and good and bad practices in C++ class interface design - including the correct function signatures for overloading arithmetic operators).
first and second both are pointer variable and holding address. and you cant add two address.
first + second is not calling you operator overloading function, try by using *first + *second
B * res = first + second; // Error here !
Here you try to assign a A* pointer (which is returned by operator+) to a B* pointer. You have to cast the result. Something like that:
B * res = dynamic_cast<B*>(first + second);
Edit: not that you should use operator overloading in this way. utnapistim gave a good answer about that.
Related
I have simple class with multiple variable for the same type :
class Hello : public HelloPure
{
private :
int X;
int Y;
int Z;
I understand how overload work, but i can't find a way to make the following logic work :
mh->X/*Or GetX()*/ += somevalue;
mh->Y/*Or GetX()*/ += somevalue2;
mh->Z/*Or GetX()*/ += somevalue3;
I couldn't figure out how to reproduce a :
void operator +=(int &val, int val2);
That would not lead to a : "too many argument" error.
My main goal is to avoid the following :
mh->SetX(mh->GetX() + somevalue);
mh->SetY(mh->GetY() + somevalue2);
mh->SetZ(mh->GetZ() + somevalue3);
The reason is that my real environement is a lot more "heavy", and an overload may be more opptimise than the current solution.
Thanks you for future answer.
Edit/Update :
A good solution found user253751, but that doesn't work in my specific situation (i'll explain after) is to return a reference :
int &GetX();
and you canse us it :
a->GetX() += 5;
But in my situation i can't do that, i'm actually transfering information between c++ anb c#.
So i have a c++ Pure class pointer that i will use to compute my data, the pointer will be initialize with a CLI (c++/c#) class inheriting from my pure class, and the Cli pointer manage a pointer to my c# class.
When i do a GetX for exemple, it's more like that :
PurePointerClass->GetX()->will call the CLI class GetX() functiun
and in the GetX() { return m_PointerToManagedC#Object->GetX(); }
This make me unable to return directly a reference to my c# variable.
A common solution is to use one or more reference wrapper classes. Depending on how different your three cases really are, you may wish to use one wrapper with mutable data, or multiple wrappers:
class Hello {
void* m_PointerToManaged = nullptr;
public:
class XRef {
void* m_PointerToManaged;
public:
XRef(void* m_PointerToManaged) : m_PointerToManaged(m_PointerToManaged) { }
void operator+=(int) {
// your code
}
};
XRef GetX() { return {m_PointerToManaged}; }
class YRef {
void* m_PointerToManaged;
public:
YRef(void* m_PointerToManaged) : m_PointerToManaged(m_PointerToManaged) { }
void operator+=(int) {
// something else
}
};
YRef GetY() { return {m_PointerToManaged}; }
class ZRef {
void* m_PointerToManaged;
public:
ZRef(void* m_PointerToManaged) : m_PointerToManaged(m_PointerToManaged) { }
// maybe Zs cannot be added to?
//void operator+=(int) {
//}
};
ZRef GetZ() { return {m_PointerToManaged}; }
};
https://godbolt.org/z/8nW6c5
The resulting object still knows about the managed object (alternatively, you can also pass this and let it use common functionality of Hello), but it is now possible to specify addition operators for an object that is only responsible for one of the three different values.
#include <stdlib.h>
#include <string>
#include <atomic>
struct base_C_event {
const char* ev;
const char* da;
};
template <class T>
struct ref_counter {
private:
std::atomic<std::ptrdiff_t> _counter;
};
struct derived_event : ref_counter<derived_event>, base_C_event {
derived_event() : event_type(), event_data() {
ev = event_type.c_str();
da = event_data.c_str();
}
std::string event_type;
std::string event_data;
};
struct derived_event2 : base_C_event, ref_counter<derived_event2> {
derived_event2() : event_type(), event_data() {
ev = event_type.c_str();
da = event_data.c_str();
}
std::string event_type;
std::string event_data;
};
struct some_cool_event {
int type;
void* payload;
};
void OnEvent(const some_cool_event* event) {
auto e = static_cast<base_C_event*>(event->payload); //...and then shows itself here
printf("%s - %s\n", e->ev, e->da);
}
int main() {
derived_event evt;
evt.event_type = "type";
evt.event_data = "Hello World";
derived_event2 evt2;
evt2.event_type = "hi";
evt2.event_data = "there";
some_cool_event my_event;
my_event.type = 1;
my_event.payload = &evt; //Problem starts here...
OnEvent(&my_event);
my_event.type = 2;
my_event.payload = &evt2;
OnEvent(&my_event);
return 0;
}
output: (compiled with g++)
(null) - type
type - Hello World
now, in my real environment (XCode) the ordering of inheritance for derived_event causes a BADACCESS exception; with g++ it just produces (null) as shown in the output.
however, the ordering for derived_event2 works just fine.
The way i understand the standard, the order of multiple inheritance effects the order of constructors and destructors, and also the layout of the memory. Can anyone explain what is happening here?
EDIT:
I have actually figured this out. The line that sets the event object to the void* payload, and then the ensuing static_cast<> back to the base type... seems to invalidate the first pointer (ev) because the struct becomes just a memory layout at that point, so the pointers are getting set to the first two pointer size chunks... in this case std::atomic<std::ptrdiff_t> and then the base_C_event. so the cast is grabbing the data for the std::atomic and using that as the pointer address for ev, and what was originally ev in the derived object is now what da points at.
I unfortunately in my real scenario can't use composition for the base_C_event in my derived_event and send that. that's why the refcounting is there, so i have to send the derived object so that later on in a callback i can decrement the refcount.
Is there a way to prevent this from happening?
Hm, I think I see where the problem lies:
struct D : B<D>, A { };
This way you inherit both a B<D> and a A instance. Effectively, this ressembles something like this:
struct D
{
B<D> implicitly_inherited_B_D;
A implicitly_inherited_A;
};
You now do the following:
D* d = new D();
void* v = d;
A* a = static_cast<A*>(v);
Problem is: v now points to the D instance, which shares its address with the inherited B<D> instance. But you cast the pointer back to A*, however, Ds A has an offset. So what you do corresponds to:
D* d = new D();
void* v = &d->implicitly_inherited_B_D;
A* a = static_cast<A*>(v);
// or equivalent:
A* aa = reinterpret_cast<A*>(&d->implicitly_inherited_B_D);
This is bound to fail...
If you want to cast back to A*, you need to make sure that your pointer actually points to the inherited A within D - which is quite easy:
D* d = new D();
void* v = static_cast<A*>(d);
// now this will work fine (v points to D's A part):
A* a = static_cast<A*>(v);
D* dd = static_cast<D*>(a); // even this one, original object was constructed as D
For comparison:
D* d = new D();
A* a = d;
D* ds = static_cast<D*>(a);
D* dr = reinterpret_cast<D*>(a); // actually undefined behaviour!!!
std::cout << d << std::endl << a << std::endl << ds << std::endl << dr << std::endl;
Assuming address of d is 0x10001000 and A within D has an offset of 8(sizeof(B<D> + possibly fill bytes for alignment), you'd see an output like this:
10001000
10001008
10001000
10001008
Note that the last line originates from the D* pointer received via reinterpret_cast!
Final note: Be aware that members can be rearranged - members declared first preceding members declared afterwards only is guaranteed for members within the same accessibility class (public/protected/private), between these sections, compiler is allowed to re-arrange. So in general you only can be safe if you go back from void* the same way you used for getting there:
void* v = d; // -> need to go back via static_cast<D*>!
A* a = static_cast<A*>(v); // requires v = static_cast<A*>(d);
B<D>* d = static_cast<B<D>*>(v); // requires v = static_cast<B<D>*>(d);
Anything else is undefined behaviour (be aware that the matter gets even worse as soon as virtual classes are involved, as then additionally there are the vtable pointers...).
If you cast a pointer to void * then always do the exact inverse cast when casting back to actual type.
So if you have :
D *d = new D;
void *v = d; // Here D* is casted to void *
When you get back the pointer, use the inverse cast. The following example are correct:
D *d2 = static_cast<D *>(v);
A *a2 = static_cast<D *>(v);
B<D> *b2 = static_cast<D *>(v);
Even better, if you can, try to avoid using void *. It can easily lead to hard-to-find bugs and this is even worst when using multiple inheritance.
If you have to use void *, then try do to it as locally as possible in the code so that ideally the conversion is done exactly at one place in the code for each direction.
class VoidMember
{
public:
void set(D *d) { v = d; }
D *get() { return static_cast<D *>(v);
private:
// In reality, you would not store a void like that but assume this is stored in
// a library / API that use `void *`
void *v;
};
While casting to other types might sometime works, it should be avoided as it make the code more fragile if code is refactored at some point like reordering base classes.
My Question:
I'm trying to overload the assignment operator for pointers to two different classes. Here is an example:
dc.h:
#ifndef DC_H_
#define DC_H_
#include "ic.h"
class dc {
double d;
char c;
public:
dc(): d(0), c(0) { }
dc(double d_, char c_): d(d_), c(c_) { }
dc* operator=(const ic* rhs);
~dc() { }
};
#endif /* DC_H_ */
class ic.h:
#ifndef IC_H_
#define IC_H_
class ic {
int i;
char c;
public:
ic(): i(0), c(0) { }
ic(int i_, char c_): i(i_), c(c_) { }
~ic() { }
};
#endif /* IC_H_ */
dc.cpp:
#include "dc.h"
dc* dc::operator=(const ic* rhs) {
d = rhs->i;
c = rhs->c;
return this;
}
ic.cpp:
#include "ic.h"
main.cpp:
#include "dc.h"
#include "ic.h"
#include<iostream>
int main() {
dc DC;
ic IC;
dc* dcptr = &DC;
ic* icptr = &IC;
dcptr = icptr;
return 0;
}
I get the following error message:
error: cannot convert 'ic*' to 'dc*' in assignment
All this works if I do it with references instead of pointers. Unfortunately since I would like to use pointers to ic and dc as members in another class I cannot use references since references as members have to be initialized and once initialized they cannot be changed to refer to another object. I'd like to be able to make arithmetic operations with ic and dc e.g.:
dc *d1, *d2, *d3;
ic *i1, *i2, *i3;
*d1 = (*d1)*(*i1) + (*i2)*(*d2) - (*d3)*(*i3);
However I want my code to look nice and don't want to have (*)*(*) all over the place. Instead something like this:
d1 = d1*i1 + i2*d2 - d3*i3;
This is the reason why I'd like to do this. Please let me know if this is possible at all. To me it seems that the compiler wants to call the default pointer to pointer assignment instead of the overloaded one.
Thanks for your help in advance!
You cannot overload operators for pointers.
One option, if you want to stick with operator overloading is to make a pointer wrapper object, an object that contains a pointer to the object - essentially a smart pointer, and overload the operators of that object.
You're given two structs. One of type 'A', another of type 'B'.
The one of type 'B' has a struct of type 'A' in it. So something like this:
struct A {
void print_stuff(A * a){ puts("From A"); }
};
struct B {
A a_part;
char * s;
void print_stuff(B * b){
printf("From B\n\t%s\n", b->s);
}
};
B * B_new(char * str) {
B * b = (B*)malloc(sizeof(struct B));
b->s = strdup(str);
return b;
}
You want to be able to call struct B's 'print_stuff' function, even with code like this:
A * aptr = (A*) B_new("foo");
aptr->print_stuff(aptr);
You are NOT allowed to use inheritance, C++ containers or classes. Struct B MUST have a_part.
How would you write your code so that regardless of the type of the pointer, the correct print_stuff function is called (in this case, if a pointer to a struct of type B was casted to A*, how would you guarantee that the print_stuff function in B is called)?
You could make print_stuff a function pointer, but then you need to manually hook it up to the correct function. In this case though, you're just replicating C++ inheritance mechanisms so it's pointless.
The A object can't automatically know where it's contained, or if it's contained at all.
So the bottom line is, just use C++ inheritance.
This is really horrible. But yes, there is a way to do it. Put a bool field in A, and in the same place in B, to indicate the real type. The code below should give you an appreciation of C++ (and really shouldn't be used for any other purpose).
struct A {
bool isB;
A()
{
isB=false;
}
void print_stuff(A * a);
};
struct B {
bool trueB;
A a_part;
char * s;
B()
{
isB=true;
}
void print_stuff(B * b){
printf("From B\n\t%s\n", b->s);
}
};
void A::print_stuff(A * a)
{
if(isB)
{
B* b = (B*)(this);
b->print_stuff(b);
}
else
puts("From A");
}
B * B_new(char * str) {
B * b = (B*)malloc(sizeof(struct B));
b->s = strdup(str);
b->trueB=true;
return b;
}
After I messed up the description of my previous post on this I have sat down and tried to convey my exact intent.
I have a class called P which performs some distinct purpose. I also have PW which perform some distinct purpose on P. PW has no member variables, just member functions.
From this description you would assume that the code would follow like this:
class P
{
public:
void a( );
};
class PW
{
public:
PW( const P& p ) : p( p ) { }
void b( );
P& p;
};
class C
{
public:
P GetP( ) const { return p; }
private:
P p;
};
// ...
PW& p = c.GetP( ); // valid
// ...
However that brings up a problem. I can't call the functions of P without indirection everywhere.
// ...
p->p->a( )
// ...
What I would like to do is call p->a( ) and have it automatically determine that I would like to call the member function of P.
Also having a member of PW called a doesn't really scale - what if I add (or remove) another function to P - this will need to be added (or removed) to PW.
You could try overriding operator* and operator-> to return access to the embedded p.
Something like this might do the trick :
class P
{
public:
void a( ) { std::cout << "a" << std::endl; }
};
class PW
{
public:
PW(P& p) : p(p) { }
void b( ) { std::cout << "b" << std::endl; }
P & operator*() { return p; }
P * operator->() { return &p; }
private:
P & p;
};
class C
{
public:
P & getP() { return p; }
private:
P p;
};
int main()
{
C c;
PW pw(c.getP());
(*pw).a();
pw->a();
pw.b();
return EXIT_SUCCESS;
}
This code prints
a
a
b
However, this method may confuse the user since the semantic of operator* and operator-> becomes a little messed up.
If you make P a superclass to PW, like you did in your previous question, you could call p->a() and it would direct to class P. It seems like you've already considered and rejected this though, judging from this question. If so, would you care to elaborate why this wont work for you?
I think you need to think through what kind of relationship exists between PW and P.
Is it an is-a relationship? Are instances of PW instances of P? Then it would make sense to have PW inherit from P.
Is it a has-a relationship? Then you should stick with containment, and put up with the syntactic inconvenience.
Incidentally, it's generally not a good idea to expose a non-const reference to a member variable in a class's public interface.