【问题标题】:Storing an object of a derived class in a reference to the base class将派生类的对象存储在对基类的引用中
【发布时间】:2014-05-06 22:19:17
【问题描述】:

我一直使用指针并避免引用,因为我不明白如何很好地使用它们。今天我正在做一个小项目,并决定改用引用并遇到一些我不知道如何解决的行为。基本上我有一个工厂(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

当我检查调试器时,在第二次创建调用之后没有 var2 的迹象。我理解它,因为我使用的是对 C 的基本类型的引用,并且只有 C 的 A 部分存储在容器中,但是有解决方法吗?我知道我可以将 A 切换到 A*,但我对是否有基于非指针的解决方案感兴趣。

TL;DR 有没有办法不使用指针将派生类的对象存储在基类的引用中?

【问题讨论】:

    标签: c++ reference pass-by-reference


    【解决方案1】:

    我不得不指出类型 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();
    

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

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

    【讨论】:

    • 我不会说引用在语法上等价于 到 const 指针;毕竟,您仍然需要取消引用指针而不是引用,这反映在语法中。
    • 你是对的。我把它改成逻辑上的,而不是句法上的。谢谢。
    • 感谢您的回答。如果我使用这个解决方案,我还需要手动删除任何内容吗?
    • 你肯定想删除对象。在 C++11(C++ 的新标准)中,您可以通过将返回值从引用更改为 std::shared_ptr 或 std::unique_ptr 来解决此问题,具体取决于您的需要。
    猜你喜欢
    • 2012-02-05
    • 2018-09-17
    • 2012-01-24
    • 1970-01-01
    • 2013-03-27
    • 1970-01-01
    • 2019-07-31
    相关资源
    最近更新 更多