扩展基类,并维护参考

时间:2013-01-23 22:45:53

标签: c++

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

例如,我的基类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上有一个答案我无法找到这个,我将非常感激。谢谢你的时间。

4 个答案:

答案 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作为入门者)我不能假设我使用静态关键字的所有含义的频率很高(特别是在函数范围内的静态变量),但是如果正确的情况出现,它们仍然是工具箱中的便利工具。