多态 C 引用

新手上路,请多包涵

我想知道 如何 使用引用而不是指针来进行多态性。

为了澄清,请参阅以下最小示例:

 class A;

class B {
  public:
    A& a; ///////////////// <- #1
    B();
    void doStuff();
};

class A {
  public:
    virtual void doSmth() = 0;
};
void B::doStuff() {
  a.doSmth();
}

class A1 : public A {
  public:
    void doSmth() {
    }
};

B::B() : a(
    *        ////////////// <- #2
      (new A1)  /////////// <- #3
     ) {
}

这可以编译并且可以工作,但是这里最重要的一点是 a#1 是一个参考,所以为了能够多态地使用它(这是一个实际的词?),如 #3 行所示,我必须通过取消引用来“将指针转换为引用”。

这让我觉得有点奇怪,我想知道是否有更好的(在 更清洁 的意义上)方法。只有我吗?

基本原理

如果我根本不需要 new 了,但是当声明(!)时 B 我不知道如何创建一个实例 A1 (!) as A 是前向声明 A1 在与 B 相同的编译单元中实现。不过,在这种情况下是否真的需要动态内存分配?你会怎么做?

抱歉,有点双重问题。

编辑

注意: B 很大(我无法为其创建模板类),并且会在程序终止时准确超出范围 a 很小,可以制作两个大模块互相交谈,只要 B 的实例存在(只有一个),就需要它。

编辑 2

I just realised, that since both A and B are effectively singletons, I can simply create a static instance of A1 in the compilation B 的单位,避免动态内存分配(即使有两个 B 他们可以轻松地使用相同的实例 A )。公平地说,我没有将此作为答案发布,但会接受促使我提出此 解决方案 的答案。

原文由 bitmask 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 357
1 个回答

没有什么奇怪的。多态性适用于指针 引用:

 struct Base { };
struct Derived : Base;

void foo(Base &);

int main() {
  Derived x;
  foo(x);    // fine
}

您将此与另一个问题混为一谈,即创建对动态对象的引用:

 T * pt = new T;
T & rt = *pt;

T & x = *new T;  // same effect

请注意, 通过引用跟踪动态对象通常是非常糟糕的风格,因为删除它的唯一方法是通过 delete &x; ,而且很难看到 x 需要清理.

There are two immediate alternatives for your design: 1) make a a member object in B , or 2) make a a shared_ptr<A>unique_ptr<A> 并将初始化程序更改为 a(new A1) 。这完全取决于您是否真的需要多态行为,即如果您有其他构造函数 B 将不同的派生类分配给 a 除了 A1

原文由 Kerrek SB 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题