0

我试图找出一种方法来获取我的基类的副本,并创建我的子类的一个实例,该实例引用与基类相同的地址空间。

例如,我的基类中有许多成员Foo,而子类中有几个额外的成员Bar。如何从我的酒吧创建一个Foo这样的变化xBar改变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上有一个我无法找到的答案,我将非常感激。感谢您的时间。

4

4 回答 4

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
于 2013-01-23T23:09:29.027 回答
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);
};

编辑:从您的评论来看,也许 inheretence 根本不是您想要的,您可能只是想使用“具有”关系将 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);
};
于 2013-01-23T23:14:32.283 回答
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. 
}
于 2013-01-23T23:15:20.550 回答
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++ 语言中有很多含义,所以如果你不熟悉的话,我建议你查看其余的(这里是C++ 静态关键字上的一个 msdn 页面 msdn 页面作为入门)我不能说我经常使用 static 关键字的所有含义(特别是函数范围内的静态变量),但是如果出现正确的情况,它们是工具箱中的方便工具。

于 2013-01-24T02:32:56.650 回答