2013-08-17 74 views
0

假设我有一个类Foo其实现涉及一个大对象。我想延长Foo的功能,所以我决定写一个类Bar它继承Foo如何获得基类实例的派生类“引用”成员的对象?

class Foo { 
protected: 
    int bigobject; 
public: 
    Foo() : bigobject(1) { } 
    int get() { return bigobject; } 
    void set(int x) { bigobject = x; } 
}; 


class Bar : public Foo { 
public: 
    Bar(Foo& f) { /* ??? */ } 
    void multiply(int factor) { bigobject *= factor; } 
}; 

正如你所看到的,我已经离开了构造的空白。这是因为我想要做的是让任何Bar对象的基本成员都是对现有Foo实例的成员的引用。换句话说,我希望代码:

Foo f; 
f.set(5); 
std::cout << "f is " << f.get() << std::endl; 

Bar b(f); 
std::cout << "b is " << b.get() << std::endl; 
b.multiply(2); 
std::cout << "b is " << b.get() << std::endl; 
std::cout << "f is " << f.get() << std::endl; 

导致:

f is 5 
b is 5 
b is 10 
f is 10 

使fb共享相同的存储空间的基础部分。这是为了避免复制bigobject任何时候我想实例化一个Bar。用非正式术语,我想Bar对象bFoo对象f的“视图”。调用Foo中的任何成员方法将会改变f,但我也可以将更多方法定义为Bar的一部分,这也将更改f。现在

,我可以宣布一个全球性的“存储”变量如:

int bigobject_storage = 1; 

class Foo { 
protected: 
    int& bigobject; 
public: 
    Foo() : bigobject(bigobject_storage) { } 
    int get() { return bigobject; } 
    void set(int x) { bigobject = x; } 
}; 

class Bar : public Foo { 
public: 
    void multiply(int factor) { bigobject *= factor; } 
}; 

为了得到我想要的功能,但是这似乎并hackish的泄漏的实施。那么,有没有一种惯用的C++方法来实现这一点?

回答

1

David Wheeler似乎是负责报价

在计算机科学中的所有问题都可以通过间接的另一个层面来解决。

这适用于您的情况:有你的基类Foo商店[智能]指针问题的大目标和整个相关实例共享相应的指针。当默认构建一个Foo对象时,会分配并指向一个大对象。当复制Foo对象时,新的Foo对象被设置为引用与原始对象相同的大对象。但是,请注意,这意味着Foo碱基的行为更像是参照彼此而不是数值。

在实际应用中,你可能会使用这样的:

class Foo { 
protected: // I don't really believe in protected data members! Don't use them! 
    std::shared_ptr<int> bigobject; 
public: 
    Foo(): bigobject(new int()) {} 
    Foo(Foo const& other): bigobject(other.bigobject()) {} 
    // ... 
}; 

Bar::Bar(Foo& other): Foo(other) { /*...*/ } 
+0

+1如果你想选择性地将分配从'Foo'(OP的“hack”的半奇数版​​本)中分离出来,那么采用'shared_ptr '的替代构造函数就足以在外部提供它。很好的答案。 – WhozCraig

+0

太好了,谢谢!这是我本周提出的第二个问题,其结果取决于初始化列表。我想我会更多地阅读它们。 – jme

0

你可以达到你想要使用的是什么没有什么比OOP概念的更多。

所有你需要做的是一个指向对象的指针,多态性将完成这项工作。

你没有在你的代码中改变任何东西,也没有必要给Bar一个Bar的副本,你所需要做的就是调用基类的构造函数(尽管这是自动完成的,的默认构造函数),在你的派生类中。

事情是这样的:

class Foo { 
protected: 
    int bigobject; 
public: 
    Foo() : bigobject(1) { } 
    int get() { return bigobject; } 
    void set(int x) { bigobject = x; } 
}; 


class Bar : public Foo { 
public: 
    Bar() : Foo() { } 
    void multiply(int factor) { bigobject *= factor; } 
}; 

诀窍是在决定要如何“视图”的对象。 因为Foo是Bar的基类,Bar拥有Foo拥有的所有东西。换句话说,Bar是Foo加上你在Bar中定义的内容。因此,指向Bar的Foo指针将表现为Foo对象,即使它指向Bar。

的代码会是这样的:

Bar b(); 
/* 
/* f and b point to the same object. 
/* But, to the compiler, f does'nt know anything of b and its methods, 
/* because f is a pointer to Foo. 
*/ 
Foo *f = &b; 
f->set(5) 
std::cout << "f is " << f->get() << std::endl; 

std::cout << "b is " << b.get() << std::endl; 
b.multiply(2); 
std::cout << "b is " << b.get() << std::endl; 
std::cout << "f is " << f->get() << std::endl; 

产生这样的结果:

f is 5 
b is 5 
b is 10 
f is 10 

即使您保存一个对象的内存,因为你使用的是同一个对象,但被视为不同的类。这是多态。

相关问题