我想知道如何使用引用(而不是指针)实现的多态性。
要澄清,请参阅以下最小示例:
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是一个引用,所以为了能够在形式上使用它(这是一个实际的单词吗?),如行#3所示,我必须通过取消引用来“将指针转换为引用”。
这让我觉得有点奇怪,我想知道是否有更好的方法(在更清洁的意义上)。就我一个人吗?
基本原理
如果我根本不需要new,那就太好了,但是当声明(!) B时,我不知道如何创建A1 (!)的实例。因为A是一个前向声明不过,在这种情况下,是否真的需要动态内存分配?你会怎么做?
不好意思问了两个小问题。
编辑
注意:B是巨大的(我不能用它创建一个模板类),当程序结束时,a就会超出范围-- a很小,并且使两个大模块相互交谈,只要B存在(只有一个),就需要它。
编辑2
我刚刚意识到,由于A和B实际上都是单例,所以我可以简单地在B的编译单元中创建A1的static实例,从而避免动态内存分配(即使有两个B,它们也可以很容易地使用相同的A实例)。平心而论,我并没有把这个作为答案,而是会接受促使我想出这个解决方案的答案。
发布于 2011-08-25 14:28:03
没什么奇怪的。多态对指针和引用都有效:
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。
发布于 2011-08-25 14:29:59
,在这种情况下,是否真的需要动态内存分配?
不是的。只需先定义A1,然后使它成为B的正常成员。
多态对于引用和指针都很好。
发布于 2011-08-25 14:30:04
这实在是有点奇怪。如果您想要一个A1类型的成员变量(而不是一个引用),为什么不重新排列您的代码,使A1的定义出现在B的定义之前?
https://stackoverflow.com/questions/7192069
复制相似问题