![](/img/trans.png)
[英]Can I Initialize a derived class reference with a base class reference to derived class instance?
[英]How can I have an object of a derived class “reference” members of an instance of the base class?
假设我有一个Foo
类,其实现涉及一个大对象。 我想扩展Foo
的功能,所以我决定编写一个继承Foo
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& 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
的基部共享相同的存储空间。 这是为了避免在我想实例化Bar
任何时候复制bigobject
。 用非正式的术语来说,我希望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; }
};
要获得我想要的功能,但这似乎有点不足,并且会泄漏实现。 那么,有没有惯用的C ++方法来完成此任务?
大卫·惠勒似乎对报价负责
计算机科学中的所有问题都可以通过另一层间接解决。
这适用于您的情况:让基类Foo
存储指向有问题的大对象的[smart]指针,并在相关实例之间共享相应的指针。 当默认构造一个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) { /*...*/ }
您可以仅使用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指针即使指向Bar也会表现为Foo对象。
代码如下:
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
甚至您也节省了一个对象的内存,因为您使用的是同一对象,但是被视为不同的类。 那就是多态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.