提问者:小点点

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


对不起,具体的例子,但我是一个牙医,我目前正在写一个牙科软件(只是作为一个爱好目前)。 我对OOP背后的理念感到非常惊讶,因为我发现把类和对象想得更容易,就好像它们是真实的一样。 我有一个基类牙齿和派生类的不同组的牙齿(他们有他们的具体情况)。 它们的构造者以被绘制的纹理为论据; 对于上牙来说是这样的:

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[12];

   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)
}


}

正如您所看到的,问题出在分配上。 我想像创建基类的数组一样创建new[],并按照派生类的顺序填充对象。 当然,如果你有完全不同的解决方案,你可以分享它,但这是我能想到的最聪明的方法。


共2个答案

匿名用户

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

…有几件事需要考虑,才能找到解决你问题的办法。

首先,是您设置的构造函数。 从一个具有参数的构造函数的类继承了子类。 那可不好,这基本上意味着你不能创建你的孩子类。 如果你尝试的话,你只会出错。 所以我把所有的构造函数都改成了“default”,这样它就可以实际运行了,但是你也应该让构建基类的子构造函数,比如

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

然后是所有权。 哪个类“拥有”牙齿数据? 您已经得到了数组,但它们是指针数组,因此它们实际上并不拥有数据。 因此您可以在其他地方拥有数据,以确保它不会在函数上下文之外被收集。 或者让数组包含牙齿的类。 我在我的解决方案中这样做是因为它更简单。 但是您可以看到upperteets仍然是一个指针数组,因为您可能不想拥有对象的两个副本。

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] };

在本例中,数组将在离开上下文时被销毁。 通过使用指针数组和新的构造函数,您可以在方法完成后继续使用数组,但是在不再需要时跟踪它并删除它,也就是在析构函数中。 更简单的方法是在主类的头中定义与我的示例中相同的“所有者数组”。

最后,对于底部的逻辑位,我用以下代码替换了您的代码:

   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[12];
    
           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 x = 0     //for the position of the tooth on the screen;
           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语句。 我所要做的就是创建一个int数组,并用它来初始化for循环中的特定类。 现在看起来是这样的:https://imgur.com/a/fghmb9y