我正试图找出一种方法来获取我的基类的副本,并创建一个我的子类的实例,它引用与基类相同的地址空间。
例如,我的基类Foo
中有许多成员,我在子类Bar
中有一些额外的成员。如何从Foo
创建一个条形图,以便更改x
中的Bar
也会更改x
中的Foo
。
离)
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);
}
我知道这是一个奇怪的问题,我没有措辞。如果有人知道答案,或者我是荒谬的,并且在stackoverflow上有一个答案我无法找到这个,我将非常感激。谢谢你的时间。
答案 0 :(得分:1)
根据您的需要/可以接近的方式,您有两种选择:
1)间接
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
};
用法:
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)多态性
struct Bar: public Foo
{
//Bar members
int z;
Bar(): Foo() { }
};
用法:
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
答案 1 :(得分:1)
当您初始化Bar时,您当前的代码会为您的Foo创建一个新的副本,这意味着它在其结构中存储了它自己的一组单独的值。为了让Foo和Bar共享一个值,您需要将其更改为指针或引用。您还需要为Bar指定一个构造函数,它将Foo作为参数。
这是一种方法,显然不理想,因为X的价值被存储为全局,最终你需要在某个地方存储它,并确切地取决于你的需要。
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);
};
编辑:根据您的评论判断,或许遗忘不是您所追求的,您可能只是想使用“有一个”关系将Foo包裹在一个Bar中,就像所以:
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);
};
答案 2 :(得分:1)
是的,所以我认为你也有能力创造你的目标:
class Foo // Base class.
{
public:
int x;
};
class Bar
{
public:
int z;
}
一些功能:
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);
除非在API中确实存在某些问题,否则你不应该需要在Foo中创建一个Bar,或者从一个Bar中创建一个Foo。那只是糟糕的设计。
编辑:
在评论中描述的情况:
某些代码会创建一个Bar对象:
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.
}
答案 3 :(得分:1)
还没有人提到的另一个选项,但如果你只想在内存中为Foo的所有对象分配一个变量作为基类,你可以使用静态成员变量。
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
}
而且,作为一个注释,静态关键字在C ++语言中有很多含义,所以如果你不熟悉我会建议你查看其余部分(这里是msdn页msdn page on the C++ static keyword作为入门者)我不能假设我使用静态关键字的所有含义的频率很高(特别是在函数范围内的静态变量),但是如果正确的情况出现,它们仍然是工具箱中的便利工具。