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

这样就f和base部分b共享同一个内存空间。这是为了避免bigobject在我想实例化Bar. 用非正式的术语来说,我希望一个Bar对象是一个对象b的“视图” 。调用任何成员方法都会改变,但我也可以定义更多方法,其中一部分也会改变。FoofFoofBarf

现在,我可以这样声明一个全局“存储”变量:

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++ 方法来实现这一点?

4

2 回答 2

1

大卫惠勒似乎对报价负责

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

这适用于您的情况:让您的基类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) { /*...*/ }
于 2013-08-17T01:23:08.483 回答
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

甚至您正在节省一个对象的内存,因为您使用的是同一个对象,但被视为不同的类。那就是多态性。

于 2013-08-17T03:13:07.963 回答