如何使用 for 循环从包含不同派生 class 的基 class 数组初始化对象?

How can I initialize objects from base class array, containing different derived classes, using a for loop?

我真的对 OOP 背后的想法感到惊讶,因为我发现更容易想到 classes 和对象,就好像它们是真实的一样。我有一个基础 class 牙齿和派生的 classes 用于不同的牙齿组(他们有自己的细节)。他们的构造函数将绘制的纹理作为参数; 对于上牙,它是这样的:

class Tooth 
{ 
   public:
   Tooth(Texture &texture);
};

class Molar : public Tooth { };
class Premolar : public Tooth { };
class Frontal : public Tooth { };

main()
{
   Molar *molar[6];
   Premolar *premolar[4];
   Frontal *frontal[6];

   Texture uppertextures[8];   //only 8 textures, since the other half of the teeth are mirrored

   Tooth* upperTeeth[16] = { molar[0], molar[1], molar[2], premolar[0], premolar[1], frontal[0], frontal[1], frontal[2], frontal[3], frontal[4], frontal[5], premolar[2], premolar[3], molar[3], molar[4], molar[5] }; // < the order in which the teeth have to be added to the graphic scene;

   int x = 0     //for the position of the tooth on the screen;
   int texture = 0;    //we will need it to assign the textures in order;

   for(int i = 0; i<16; i++)
   {
       upperTeeth[16] = new !?!?!?(uppertextures[i])
       upperTeeth[16]->setPositionX(i+x) // some function for setting the position on the screen from left to right;
       
       if(i<8) texture++;     //setting the textures for the teeth on the left;
       if(i>8) texture--;    //setting the textures for the teeth on the right(the same, but in reverse order);
       
       upperTeeth[16]->setPositionY(y)
}


}

如您所见,问题出在分配上。我想以创建 Base class 数组的相同方式创建 new[],并填写对象出现的派生 classes 的顺序。当然,如果你有完全不同的解决方案,你可以分享,但这是我能想到的最聪明的方法。

很多人会告诉您“拿一本教科书”的原因是因为 C++ 中有很多机器在运行。但是别担心,没有它你可以学到很多东西。实践可能是最好的学习方式。

...找到问题的解决方案需要考虑一些事项。

首先,是您设置的构造函数。你有 child class 继承自 class 的元素,后者具有带参数的构造函数。这不好,这基本上意味着您无法创建 child classes。如果你尝试,你只会得到错误。所以我已经将所有构造函数更改为“默认”以便它实际运行,但是你也应该制作 child 构建基础 class 的构造函数,比如

Molar(Texture& texture) 
    : Tooth(texture) 
{
    // ... do whatever here
}

然后是所有权。哪个class“拥有”牙齿数据?你有你的数组,但它们是指针数组,所以它们实际上并不拥有数据。因此,您可以在其他地方拥有数据,以确保它不会 trash-collected 在您的函数上下文之外。 或者 只是让数组实际包含牙齿 classes。我已经在我的解决方案中这样做了,因为它更简单。但是您可以看到 upperTeeth 仍然是一个指针数组,因为您可能不想拥有 objects.

的两个副本
Molar molar[6];
Premolar premolar[4];
Frontal frontal[12];

Texture uppertextures[8];   // Only 8 textures, since the other half of the teeth are mirrored

// The order in which the teeth have to be added to the graphic scene
Tooth *upperTeeth[16] = { &molar[0], &molar[1], &molar[2], &premolar[0], &premolar[1], &frontal[0], &frontal[1]
                          , &frontal[2], &frontal[3], &frontal[4], &frontal[5], &premolar[2], &premolar[3], &molar[3]
                          , &molar[4], &molar[5] };

在此示例中,数组将在离开上下文时被销毁。通过使用指针数组和 new 构造函数,您可以在方法完成后继续使用该数组,但要跟踪它并在不再需要时将其删除,也就是在析构函数。更简单的方法是在 main class.

的 Header 中定义与我的示例相同的“所有者数组”

最后是底部的逻辑位,我将您的代码替换为:

   int x = 0;     // For the position of the tooth on the screen;
   int y = 0;     // Why not a y variable as well?
   int texture = 0;    // We will need it to assign the textures in order;

   for(int i = 0; i<16; i++) {
       upperTeeth[i]->setPositionX(i + x); // Some function for setting the position on the screen from left to right;

       if (i < 8) texture++;     // Setting the textures for the teeth on the left;
       if (i > 8) texture--;    // Setting the textures for the teeth on the right(the same, but in reverse order);

       upperTeeth[i]->setTexture(texture); // alternative to your constructor

       upperTeeth[i]->setPositionY(y);
   }

注意你错过了使用 [i] 而不是 [16] 的地方。或者,您可以使用

直接遍历数组
 int i = 0;
 for (auto tooth : upperTeeth) {
      tooth->setPositionX(i); // you still need i for your case.
      i++;
 }

希望我能解决一些问题!

我终于做了我想做的事。这个问题纯粹是合乎逻辑的。对于所有说我不应该子类化的人 - 我已经制作了一个程序版本,其中没有派生 类 的牙齿,在某些时候我觉得它太局限了。现在我发布了有效的代码:

    class Tooth 
    { 
       public:
       Tooth(Texture &texture);
    };
    
    class Molar : public Tooth { };
    class Premolar : public Tooth { };
    class Frontal : public Tooth { };
    
    main()
    {
       Molar *molar[6];
       Premolar *premolar[4];
       Frontal *frontal[6];
    
           Texture texture[8];   //only 8 textures, since the other half of the teeth are mirrored
         
           int toothindex[16] = { 0, 1, 2, 0, 1, 0, 1, 2, 3, 4, 5, 2, 3, 3, 4, 5 };
        
           int textureindex = 0;    //we will need it to assign the textures in order;
        
           for(int i = 0; i<16; i++)
           {
               if(i < 3 || i>12) 
               molar[toothindex[i]] = new Molar(texture[index]);
            
               if(i==3; i==4; i==11; i==12)
               premolar[toothindex[i]] = new Premolar(texture[textureindex]);
    
              if(i>4 && i<12) frontal[toothindex[i]] = new Frontal(texture[textureindex])
    
           if(i<7) texture++; 
           if(i>7) texture--;  
          }
   }  
       

感谢您告诉我所谓的未定义行为并提出 if 语句。我所要做的就是创建一个整数数组,并用它来初始化 for 循环中的特定 类。现在看起来像这样:https://imgur.com/a/fghmb9Y

哦...因为我使用的是指针数组,对于任何寻求答案的人,不要忘记制作某种 for 循环来删除不需要的对象:

for (int i = 0; i<6; i++)
{
    if(i<4) delete premolar[i];
    delete molar[i];
    delete frontal[i];
}