多态 C++ 引用
我想知道如何用引用来实现多态,而不是指针.
I was wondering how you can do polymorphism with references, as opposed to pointers.
为了澄清,请参阅以下最小示例:
To clarify, see the following minimal example:
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
所示,我必须将指针转换为引用";通过取消引用它.
This compiles and works, but as the most important point here is that a
in line #1
is a reference, so in order to be able to use it polymorphically (is that an actual word?), as shown in line #3
I have to "convert a pointer to a reference" by dereferencing it.
这让我觉得有点奇怪,我想知道是否有更好的(在更清洁的意义上)方法.只有我吗?
This strikes me as a bit odd, and I was wondering if there is a better (in the sense of cleaner) way. Is it just me?
如果我根本不需要 new
那就太好了,但是在声明 (!) B
时,我不知道如何创建 A1
(!) as A
是前向声明 -- A1
与 B
在同一编译单元中实现.尽管如此,在这种情况下是否真的需要动态内存分配?你会怎么做?
It would be great if I didn't need a new
at all, but when declaring (!) B
I have no clue how to create an instance of A1
(!) as A
is a forward declaration -- A1
is implemented in the same compilation unit as B
. Still, is there a real need for dynamic memory allocation in this case? How would you do this?
抱歉让我有点双重问题.
Sorry for the slightly twofold question.
注意:B
很大(我不能为它制作模板类),并且会在程序终止时精确地超出范围 -- a
很小并使两个大模块相互通信,只要 B
的实例存在(只有一个),就需要它.
Note: B
is huge (and I cannot make a template class of it), and will go out of scope precisely when the program terminates -- a
is small and makes two big modules talk to each other, it will be needed as long as the instance of B
lives (there is only one).
我刚刚意识到,由于 A
和 B
都是有效的单例,我可以简单地创建 A1 的
在static
实例B
的编译单元中,避免动态内存分配(即使有两个B
也很容易使用A<的同一个实例/代码>).公平地说,我没有将此作为答案发布,但会接受促使我提出此解决方案的答案.
I just realised, that since both A
and B
are effectively singletons, I can simply create a static
instance of A1
in the compilation unit of B
, avoiding dynamic memory allocation (even if there were two B
s they could easily use the same instance of A
). To be fair, I did not post this as answer, but will accept the answer that prompted me to come up with this solution.
推荐答案
没有什么奇怪的.多态适用于指针和引用:
There's nothing odd. Polymorphisms works both for pointers and references:
struct Base { };
struct Derived : Base;
void foo(Base &);
int main() {
Derived x;
foo(x); // fine
}
您将此与另一个问题混为一谈,即创建对动态对象的引用:
You're conflating this with another issue, namely creating a reference to a dynamic object:
T * pt = new T;
T & rt = *pt;
T & x = *new T; // same effect
请注意,仅通过引用跟踪动态对象通常是非常糟糕的风格,因为删除它的唯一方法是通过delete &x;
,并且很难看出 x
需要清理.
Note that it's generally very bad style to track a dynamic object only by reference, because the only way to delete it is via delete &x;
, and it's very hard to see that x
needs cleaning up.
您的设计有两种直接的替代方法:1) 将 a
设为 B
中的成员对象,或 2) 将 a
设为 shared_ptr
或 unique_ptr
并将初始化器更改为 a(new A1)
.这完全取决于您是否真的需要多态行为,即如果您有其他的 B
构造函数,它们将不同的派生类分配给 a
而不是 A1代码>.
There are two immediate alternatives for your design: 1) make a
a member object in B
, or 2) make a
a shared_ptr<A>
or unique_ptr<A>
and change the initalizer to a(new A1)
. It all depends on whether you actually need the polymorphic behaviour, i.e. if you have other constructors for B
which assign a different derived class to a
other than A1
.
相关文章