繁体   English   中英

在对基类的引用中存储派生类的对象

[英]Storing an object of a derived class in a reference to the base class

我一直使用指针,并且避免使用引用,因为我不了解如何很好地使用它们。 今天,我正在做一个小项目,决定改用引用,然后遇到一些不确定的行为。 基本上,我有一个工厂(Factory)创建一个类型为B或C的对象,这两个对象均从A派生。

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调用之后没有var2的迹象。 我理解它是因为我使用的是对C的基本类型的引用,并且仅C的A部分存储在了容器中,但是有解决方法吗? 我知道我可以将A切换为A *,但是我对是否存在基于非指针的解决方案感兴趣。

TL; DR是否可以在不使用指针的情况下将派生类的对象存储在基类的引用中?

我不得不指出,类型T的引用在逻辑上等效于T * const。 因此,从技术上讲,您无法使用指针。

为了回答您的问题,绝对有可能将派生类存储在对基类的引用中。 问题在于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;
  }
};

像这样称呼:

Factory factory;
A &a1 = factory.Create(0);
A &a2 = factory.Create(1, 2); 

a1.Function();
a2.Function();

将打印:B:0 C:1,2

不幸的是,由于它们的大小不匹配,因此不可能先分配A,然后再为其分配B或C。 您要么必须使用具有动态分配的引用/指针,要么提前知道类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM