C++传递函数指针数组

C++传递函数指针数组,c++,pointers,C++,Pointers,我在向函数传递指针数组时遇到问题 CTree01类是CDECoOptionObj的子类。 当我使用for循环时,它工作得很好 这是我的密码: CTree01 *trees01; int numTree01 = ...; trees01 = new CTree01[numTree01]; //main loop for(int i=0;i<numTree01;i++) { { //Everything is working okay her

我在向函数传递指针数组时遇到问题

CTree01类是CDECoOptionObj的子类。 当我使用for循环时,它工作得很好

这是我的密码:

CTree01 *trees01;
int numTree01 = ...;

trees01 = new CTree01[numTree01];

//main loop
for(int i=0;i<numTree01;i++)
    {
        {
            //Everything is working okay here, renders all trees
            glPushMatrix();
            trees01[i].DrawOnTerrain(camera);
            glPopMatrix();
        }
    }

它可以工作,只有当我渲染索引大于0的对象时才会崩溃,所以我认为传递给函数的参数一定有问题。

让我看看是否可以用几个简单的类来解释这个问题

假设你有:

struct Foo
{
   char a;
};

struct Bar : Foo
{
   char b;
};
sizeofFoo为1,SizeOffbar为2

并使用以下方法创建条形图对象数组:

Bar* barPtr = new Bar[2];
barPtr指向的内存布局如下所示:

Bar(0)  Bar(1)
|       |
v       v
+---+---+---+---+
| a | b | a | b |
+---+---+---+---+
如果将该指针传递给函数a Foo*,该函数将解释内存,因为sizeofFoo==1:

正如您所看到的,Foo1并不是一个真正的Foo对象。它实际上是Bar0的Bar子对象。这很容易导致未定义的行为。根据基类和派生类拥有的数据类型,它很容易使程序崩溃


关键的一点是,指向派生类对象数组的指针不能被视为指向基类对象数组的指针。

来自R Sahu的非常好的解释。它清楚地描述了为什么您的代码不起作用,并且值得接受

那么你能做些什么呢

据我所知,您希望在一次调用中将所有CTree01传递给一个函数,并让该函数迭代所有CTree01

我知道的唯一方法是制作容器,即数组,向量,它包含基类指针,而不是CTree01

大概是这样的:

class A
{
public:
    A() { cout << "A constructor" << endl;}
    virtual ~A() { cout << "A destructor" << endl;}
    void hello() { cout << "Hello from A" << endl;}
};

class B : public A
{
public:
    B() { cout << "B constructor" << endl;}
    ~B() override { cout << "B destructor" << endl;}
};

void f(array<A*,2>& t)
{
    for(auto e : t)
    {
        e->hello();
    }
}

int main()
{
    array<A*,2> z;   // Base class pointer array
    z[0]=new B;      // but it can still hold pointers to B
    z[1]=new B;
    f(z);
    delete z[0];
    delete z[1];
    return 0;
}
或者使用向量代替数组

class A
{
public:
    A() { cout << "A constructor" << endl;}
    virtual ~A() { cout << "A destructor" << endl;}
    void hello() { cout << "Hello from A" << endl;}
};

class B : public A
{
public:
    B() { cout << "B constructor" << endl;}
    ~B() override { cout << "B destructor" << endl;}
};

void f(vector<A*>& t)
{
    for(auto e : t)
    {
        e->hello();
    }
}

int main()
{
    vector<A*> z;
    z.push_back(new B);
    z.push_back(new B);
    f(z);
    delete z[0];
    delete z[1];
    return 0;
}

您使用类型CDecorationObj处理objs[]-数组,它的长度肯定与CTree01不同,比如说,CDecorationObj的大小为10字节,CTree01的大小为20字节,当您访问objs[1]时,您只是进入下一个树对象内存的一半,在调用Drawonterain时,您得到了一个错误的地址。尝试使用指向内部元素的指针,例如CTree**和CDecorationObj**您不应该仅仅因为这样就进行更新和删除,尤其不应该将原始指针用作数组。Google std::vector。我用CDecorationObj**objs替换了CDecorationObj*objs,但现在出现了一个错误,无法将参数1从'D_CTree02**'转换为'CDecorationObj**'@Barcio77 Ok,但这还不够^^^^您还必须为每个CTree分配新的参数-我希望您也这样做了。考虑到我们的身体增强的糕点朋友的上述评论,你应该考虑使用STD::矢量。另见下面R Sahu的答案,他更详细地解释了我所说的。底线是,你需要给出一个指向元素的指针列表,可以是指向基的指针,也可以是指向基的指针向量。好的,我现在明白了,它正在工作!谢谢你写下这个解决方案
Foo(0)  
|   Foo(1)
|   |
v   v
+---+---+
| a | a |
+---+---+
class A
{
public:
    A() { cout << "A constructor" << endl;}
    virtual ~A() { cout << "A destructor" << endl;}
    void hello() { cout << "Hello from A" << endl;}
};

class B : public A
{
public:
    B() { cout << "B constructor" << endl;}
    ~B() override { cout << "B destructor" << endl;}
};

void f(array<A*,2>& t)
{
    for(auto e : t)
    {
        e->hello();
    }
}

int main()
{
    array<A*,2> z;   // Base class pointer array
    z[0]=new B;      // but it can still hold pointers to B
    z[1]=new B;
    f(z);
    delete z[0];
    delete z[1];
    return 0;
}
class A
{
public:
    A() { cout << "A constructor" << endl;}
    virtual ~A() { cout << "A destructor" << endl;}
    void hello() { cout << "Hello from A" << endl;}
};

class B : public A
{
public:
    B() { cout << "B constructor" << endl;}
    ~B() override { cout << "B destructor" << endl;}
};

void f(vector<A*>& t)
{
    for(auto e : t)
    {
        e->hello();
    }
}

int main()
{
    vector<A*> z;
    z.push_back(new B);
    z.push_back(new B);
    f(z);
    delete z[0];
    delete z[1];
    return 0;
}