Reputation: 1903
I'm trying to figure out a way to take a copy of my base class, and create an instance of my subclass that references the same address space as the base class.
So for example, I have a number of members in my base class Foo
, and I have a couple extra members in the subclass Bar
. How do I create a Bar from my Foo
such that changing x
in Bar
also changes x
in Foo
.
ex)
struct Foo{
int x;
Foo(){
x = 0;
}
}
struct Bar : Foo{
int z;
//?? what to do here
}
int main(){
Foo foo();
Bar bar(foo); //??
bar.x = 7;
assert(bar.x == foo.x);
}
I know this is a strange question, and I haven't worded it very well. If anyone knows an answer or if I'm being ridiculous and there is an answer on stackoverflow that I just can't find fort this, I will be very appreciative. Thank you for your time.
Upvotes: 0
Views: 156
Reputation: 664
Just another option that no one has mentioned yet, but if you want only a single variable allocated in memory for all objects of with Foo as a base class, you can use static member variables.
struct Foo{
static int x;
Foo() {
x = 0;
}
};
int Foo::x = 0;
struct Bar : Foo {
int z;
};
int main(){
Foo foo();
Bar bar();
bar.x = 7;
assert(&bar.x == &foo.x); // now using the same memory address
}
And, as a note, the static keyword has many meanings in the C++ language so I would suggest looking the rest of them up if you are unfamiliar (here is an msdn page msdn page on the C++ static keyword as a starter) I cannot say I use all meanings of the static keyword with much frequency (particularly static variables at function scope), but they are handy tools to have in the tool box nonetheless should the correct situation present itself.
Upvotes: 1
Reputation: 129344
Right, so I'm goiing to assume that you also have the ability to create your objeccts:
class Foo // Base class.
{
public:
int x;
};
class Bar
{
public:
int z;
}
Some function:
void frobb(Foo *fooPtr)
{
if(fooPtr->x != 7)
{
cout << "Bad value of x\n";
}
...
}
....
// some of your code (in a different file probably.
Bar b;
... do stuff with b.
b.x = 7;
frobb(&b);
Unless there is really something broken in the API, you shouldn't ever need to make a Bar out of a Foo, or a Foo from a Bar. That's just bad design.
Edit:
In the case described in the comment:
Some code creates a Bar object:
Bar b;
extern void some_generic_api(Foo *fptr);
... do stuff with b, including setting your own variables.
b.x = 7;
some_generic_api(&b); // WOrks like a "Foo" object without problem.
... some other bit of code ...
void frobb(Foo *fptr)
{
// Note: Don't do this unless you are SURE it's a Bar object you actually have!
Bar *bptr = reinterpret_cast<Bar*>(fptr);
.. do stuff that requires Bar object using bptr;
bptr->x = 19;
some_generic_api(bptr); // This will work fine.
}
Upvotes: 1
Reputation: 1236
Depending on how you want/can approach this, you've got two options:
1) Indirection
struct Bar
{
private:
Bar() = delete; //eradicate the default constructor
public:
//Foo member references
int &x;
//Bar members
int z;
Bar(Foo& f): x(f.x) { } //of course, you may initialize z as well
};
Usage:
Foo foo_obj;
//new scope begins (can be a function call, for example)
{
Bar bar_obj(foo_obj);
//do stuff with bar_obj
//...
//work done
} //scope ends; bar_obj is destroyed
//magic! foo_obj has been updated with the correct values all this time
2) Polymorphism
struct Bar: public Foo
{
//Bar members
int z;
Bar(): Foo() { }
};
Usage:
Foo foo_obj;
//new scope begins (can be a function call, for example)
{
Bar bar_obj;
static_cast<Foo&>(bar_obj) = foo_obj; //we'll use Foo's default (or user-defined) assignment operator
//note that you need to cast to reference
//do stuff with bar_obj
//...
//work done
foo_obj = bar_obj; //you will need to copy your data back at this point
//also note foo_obj has not been updated during this time, which may not be desirable
} //scope ends
Upvotes: 1
Reputation: 317
Your current code makes a fresh copy of your Foo when you initialize the Bar, this means it has it's own set of separate values stored within it's structure. In order to let the Foo and Bar share a value you will need to change it to a pointer or reference. You will also need to specify a constructor for Bar that takes a Foo as it's argument.
Here's one way to do it, obviously not ideal because the value of X is being stored as a global, ultimately you are going to need somewhere to store it and exactly where that is depends on your needs.
int x_storage;
struct Foo{
int& x;
Foo(): x(x_storage){
x = 0;
}
};
struct Bar : Foo{
int z;
Bar(Foo& f)
{
x = f.x;
}
};
int main(){
Foo f = Foo();
Bar b = Bar(f); //??
b.x = 7;
assert(b.x == f.x);
};
EDIT: Judging by your comments, perhaps inheretence isn't what you are after at all, you may simply want to use a "has a" relationship to wrap a Foo inside a Bar, like so:
struct Foo{
int x;
Foo(){
x = 0;
}
};
struct Bar{
Foo& myFoo;
int z;
Bar(Foo& f): myFoo(f){
}
};
int main(){
Foo f = Foo();
Bar b = Bar(f); //??
b.myFoo.x = 7;
assert(b.myFoo.x == f.x);
};
Upvotes: 1