如何使用结构体作为接口从函数返回指向数组的指针

how do I return a pointer to an array from a function using a struct as the interface

本文关键字:返回 数组 指针 函数 结构体 何使用 接口      更新时间:2023-10-16

我试图在c++中创建一个数组接口。


在下面的代码中
tmpClass[1].GetA()返回'w'
tmpInterface[1]出错

有没有办法定义一个接口,使它可以访问数组的元素?
如何让tmpInterfacetmpClass一样?

struct IA
{
    virtual char GetA() = 0;
    virtual void SetA(char pA) = 0;
};
class A:public IA
{
    public:
        A(){ var = 0; }
        A(char pVar){ var = pVar; }
        char GetA(){ return var; }
        void SetA(char pA){ var = pA; }
    private:
    int var;
};
class B
{
    public:
        B(){ 
            mA[0].SetA('c');
            mA[1].SetA('w');
            mA[2].SetA('6');
            mA[3].SetA('$');
        }
        int GetCount(){}
        IA* Get1(){ return mA; }
        A* Get2(){ return mA; }
    protected:
        A mA[4];
};

int main()
{
    B mainClass;
    IA *tmpInterface = mainClass.Get1();
    A *tmpClass = mainClass.Get2();
    for (int i = 0; i < 4; i++)
    {
        //once i>0 then tmpInterface no longer points to a valid character
        //and program crashes
        System::Console::Write(
            "A = "+tmpClass[i].GetA()+
            " IA = "+tmpInterface[i].GetA()); 
    }
    return 0;
}

下标操作符使用指针算术操作,在不同类型的指针上执行指针算术操作是未定义的行为。§5.7 [expr.add]/p7:

对于加法或减法,如果表达式PQ具有类型"指向cv T的指针",其中T与cv-不限定值不同数组元素类型,其行为未定义。[注意: In。特别地,指向基类的指针不能用作指针当数组包含派生类类型的对象时。- 结束说明]

因此,要索引A s数组,您需要一个A*。如果您只想使用IA,那么您需要应用一些程序员的灵丹妙药-间接。返回一个指向IA *数组第一个元素的IA **,该数组的每个成员都指向A

请注意,多态性只适用于指向类实例的指针或引用,而不是直接适用于实例。这是你问题的根源。

您可以考虑使用std::vector<A*>而不是数组

在类型为B的对象中,您有一个A对象数组。在成员函数B::Get1()B::Get2()中都返回指向数组第一个元素的指针。

假设数组的布局是:

+--------------+--------------+--------------+--------------+
|    mA[0]     |    mA[1]     |    mA[2]     |    mA[3]     |         
+--------------+--------------+--------------+--------------+

当你执行

IA *tmpInterface = mainClass.Get1();
A *tmpClass = mainClass.Get2();

你有tempInterfacetmpClass指向mA的第一个元素。

+--------------+--------------+--------------+--------------+
|    mA[0]     |    mA[1]     |    mA[2]     |    mA[3]     |         
+--------------+--------------+--------------+--------------+
^
| 
tmpInterface as well as tmpClass

当你对tmpInterfacetmpClass进行算术运算时,你会看到非常不同的结果。

tmpInterface+1tmpClass+1在哪里?

+--------------+--------------+--------------+--------------+
|    mA[0]     |    mA[1]     |    mA[2]     |    mA[3]     |         
+--------------+--------------+--------------+--------------+
      ^        ^
      |        | 
      |        tmpClass+1
      tmpInterface+1

由于tmpClass的类型是A*,因此tmpClass+1指向数组中的下一个对象。但是,由于tmpInterface的类型是IA*, sizeof(IA)sizeof(A)不一样,所以tmpInterface+1指向中间的东西。它不指向IA类型的对象。如果你试图访问tmpInterface+1作为IA*,你将得到未定义的行为。

在有效的c++中,它说不要在数组上使用多态性;您可以添加一个类似于操作符[]的虚函数,例如:

struct IA
{
    //...
    virtual IA* Offset(int index)
    {
        return this + index;
    }
};
class A:public IA
{
public:
    //...
    virtual A* Offset(int index)
    {
        return this + index;
    }
};

那么它可以正常工作。

cout << "A = " << tmpClass->Offset(i)->GetA();
cout << " IA = " << tmpInterface->Offset(i)->GetA() << endl;

另外,什么是System::Console::Write in c++ ?