C++ 在对基类的引用中存储派生类的对象
我总是使用指针,避免引用,因为我不太了解如何使用指针。今天我在做一个小项目,决定改用引用,遇到了一些行为,我不知道该如何处理。基本上,我有一个工厂(factory),它创建类型B或C的对象,这两种对象都是从a派生的C++ 在对基类的引用中存储派生类的对象,c++,reference,pass-by-reference,C++,Reference,Pass By Reference,我总是使用指针,避免引用,因为我不太了解如何使用指针。今天我在做一个小项目,决定改用引用,遇到了一些行为,我不知道该如何处理。基本上,我有一个工厂(factory),它创建类型B或C的对象,这两种对象都是从a派生的 class Factory { public: void create(A& container, int a) //This is for creating an object of B { B result; result.
class Factory
{
public:
void create(A& container, int a) //This is for creating an object of B
{
B result;
result.Func(a);
container = result;
}
void create(A& container, int a, int b) //This is for creating an object of C
{
C result;
result.Func(a, b);
container = result;
}
}
class A
{
public:
virtual void Func(int a) //This is used for an object of B
{
var1 = a;
};
virtual void Func(int, int) {}; // This is used for an object of C
private:
int var1;
}
class B : public A
{
//Relies of base class Func to set the variable var1;
}
class C : public A
{
public:
void Func(int a, int b)
{
A::Func(int a)
var2 = a1;
}
private:
int var2;
}
当我尝试执行以下操作时,问题就出现了
Factory factory;
A a;
factory.create(a, 1); //Works fine because B and A have only 1 variable
factory.create(a, 1, 1); //a only contains A part of C
当我检查调试器时,在第二次create调用之后,在a中没有var2 to的迹象。我理解它是因为我使用了对C的基类型的引用,并且只有C的a部分存储在容器中,但是有解决方法吗?我知道我可以将A切换到A*,但我感兴趣的是是否有一个非基于指针的解决方案
TL;博士
有没有一种方法可以在不使用指针的情况下将派生类的对象存储在基类的引用中?我不得不指出,T类型的引用在逻辑上等同于T*常量。所以从技术上讲,你不能用指针四处走动 为了回答您的问题,绝对可以将派生类存储在对基类的引用中。问题是A、B和C的尺寸都可能不同。这里有一个解决方案:
#include <stdio.h>
class A
{
public:
virtual void Function()
{
printf("A\n");
}
};
class B : public A
{
public:
virtual void Function()
{
printf("B: %d\n", var1);
}
int var1;
};
class C : public A
{
public:
virtual void Function()
{
printf("C: %d, %d\n", var1, var2);
}
int var1, var2;
};
class Factory
{
public:
A & Create(int a)
{
B &b = *new B;
b.var1 = a;
return b;
}
A & Create(int a, int b)
{
C &c = *new C;
c.var1 = a;
c.var2 = b;
return c;
}
};
将打印:
B:0
C:1,2
不幸的是,不可能先分配A,然后再分配B或C,因为它们的大小不匹配。您必须使用具有动态分配的引用/指针,或者提前知道类型。我不会说引用在语法上等同于常量指针;毕竟,您仍然需要取消对指针的引用,而不是对引用的引用,这反映在语法中。您是对的。我把它改为逻辑上的,而不是语法上的。谢谢,谢谢你的回答。如果我使用此解决方案,是否仍需要手动删除任何内容?您肯定要删除对象。在C++11(C++的新标准)中,可以通过将返回值从引用更改为std::shared_ptr或std::unique_ptr来解决这个问题,具体取决于您的需要。
Factory factory;
A &a1 = factory.Create(0);
A &a2 = factory.Create(1, 2);
a1.Function();
a2.Function();