我想知道如何使用引用而不是指针来实现多态性。
为了澄清,请参见以下最小示例:
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
) {
}
这可以编译并且可以工作,但是这里最重要的一点是 #1
行中的 a
是一个引用,所以为了能够多态地使用它(这是一个实际的词吗?),如 #3
行所示,我必须通过取消引用来“将指针转换为引用”。
这让我觉得有点奇怪,我想知道是否有更好的(在 cleaner 的意义上)方法。只有我吗?
基本原理
如果我根本不需要 new
那就太好了,但是在声明 (!) B
时,我不知道如何创建 A1
(!) as A
是前向声明 - A1
与 B
在相同的编译单元中实现。不过,在这种情况下是否真的需要动态内存分配?你会怎么做呢?
抱歉,有点双重问题。
编辑
注意:B
很大(我不能为它创建一个模板类),并且会在程序终止时恰好超出范围——a
很小并使两个大模块相互通信,只要 B
的实例存在(只有一个)就需要它。
编辑 2
我刚刚意识到,由于 A
和 B
都是有效的单例,我可以简单地创建 A1 的
在static
实例B
的编译单元中,避免动态内存分配(即使有两个B
也可以轻松使用相同的A< 实例
)。公平地说,我没有将此作为答案发布,但会接受促使我提出此解决方案的答案。
最佳答案
没有什么奇怪的。多态性适用于指针 和 引用:
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
需要清理。
您的设计有两种直接的选择:1) 制作 a
B
中的成员对象, 或 2) 制作 a
一个 shared_ptr<A>
或 unique_ptr<A>
并将初始化程序更改为 a(new A1)
.这完全取决于您是否真的需要多态行为,即是否有其他构造函数用于 B
将不同的派生类分配给 a
除了 A1
.
关于c++ - 多态 C++ 引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7192069/