繁体   English   中英

我怎样才能让派生类的对象“引用”基类实例的成员?

[英]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

这样fb的基部共享相同的存储空间。 这是为了避免在我想实例化Bar任何时候复制bigobject 用非正式的术语来说,我希望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; }
};

要获得我想要的功能,但这似乎有点不足,并且会泄漏实现。 那么,有没有惯用的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM