假设我有一个类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
因此f
和b
的基本部分共享相同的内存空间。这是为了避免在我想要实例化bigobject
的任何时候复制Bar
。在非正式的术语中,我希望Bar
对象b
成为Foo
对象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 ++方法来实现这个目标呢?
答案 0 :(得分: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) { /*...*/ }
答案 1 :(得分: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
即使您正在保存一个对象的内存,因为您使用的是同一个对象,但被视为不同的类。那就是多态性。