【问题标题】:Pass parent data members value to child class将父数据成员值传递给子类
【发布时间】:2017-02-24 03:30:56
【问题描述】:

该程序的目的是生成扬声器外壳的模拟脚本。

因此我有一个定义演讲者的班级演讲者。

一个父类外壳,包含所有外壳的公共参数。

具有自身特殊属性的子类。

使用多态性和继承,我获得了第一个运行良好的程序,但我每次都需要重新计算外壳的基本属性:

class speaker
{     
}
class Enclosure
{ 
        int m_boxHeight;
        speaker * m_speakerBass;//...
        public://some functions
}
class closedBox : public Enclosure
{        
    public: 
        closedbox(speaker &speakerbass):Enclosure(speakerbass)//    some functions            
    protected:
        int paramclosed1;//...            
 }

int main()
{    
    speaker speakerbass;

    cout <<endl<< "Please choose in the available enclosure proposals" << endl;
    cout << "1 Closed box enclosure" << endl;
   // cout << "2 Bass reflex enclosure" << endl;
   // cout << "3 and so on..." << endl;
    int choice;
    cin>>choice;
          switch (choice)
      {
         case 1:
            closedbox * ClBox2Simu;
            ClBox2Simu= new closedbox(speakerbass);       
            delete ClBox2Simu;
            break;
         case 2:
             //... same but with bassreflex class child    
            break;

         default:
            cout<<"Then good bye";

      }
    return 0;
}

在我的程序中,父类的成员数据可以提供给子类。我的意思是,Enclosure 的框尺寸在每个子类bassreflexclosedbox 中都是相同的。

如果有办法,我现在会这样做:

  • 创建父类

  • 进行第一次初始一般计算

  • 使用父参数创建子节点(问题)

这基本上意味着 child=parent 这是被禁止的。 在这段代码的想法中:

class speaker
{
    public:        //    some functions
    protected:
        int fs;
        int paramSpeaker2;            //...    
}
class Enclosure
{    
    public:            //some common function
    protected:
        int m_boxHeight;
        speaker *m_speakerBass //...    
}
class closedBox : public Enclosure
{    
    public:
        closedbox();  //    some functions
    protected:
        int paramclosed1;  //...    
}
class bassreflex : public Enclosure
{    
    public:
        bassreflex();  //    some functions
    protected:
        int paramclosed1;   //...    
}

int main()
{    
    Enclosure initialBox;// calculate dimension,choose speaker...

            closedbox * ClBox2Simu;
            ClBox2Simu= initialBox;//  child= parent which is forbidden
            //do stuff concerning closedbox
            delete ClBox2Simu;

            bassreflex * BassReflex2Simu;
            BassReflex2Simu= initialBox; //forbidden
            //do stuff concerning bassreflex
            delete BassReflex2Simu;

             //... and so on for other child class using enclosure

      delete initialBox
    return 0;
}

希望清楚!

【问题讨论】:

  • 为什么不直接初始化子类呢?是时候阅读Constructors and member initializer lists
  • 我不明白您在哪里(或为什么)“重新计算基本属性”?
  • 第一个例子中的动态分配是完全没有必要的。
  • @Danh,@UnholySheep 这就是我在第一个程序中所做的,我想在第二个中做的是计算公共属性,例如:Enclosure commonEnclosure 然后声明子类@987654328 @, bassreflex box2 与父 commonEnclosure 的参数。
  • @Boulgour 你可以在基本构造函数中进行常见的初始化,对吧?

标签: c++ inheritance


【解决方案1】:

您描述的症状表明典型的 is-ahas-a,即继承与构图问题。

在 C++ 中,原则是创建子对象。 child的构造过程是:

  • 首先构造一个封闭的父对象
  • 然后构造子节点的成员
  • 最后,子构造函数体被执行以完成构造。

一旦你对这个逻辑有疑问,它表明继承可能不是最好的方法。 OOP 中通常的建议是优先组合而不是继承。原则上,仅当对象的性质不变时才应使用继承。

由于我不熟悉您的域,这里有一个典型且更熟悉的示例:

class animal {}; 
class cat : public animal {};  // ok:  a cat will always remain an animal

class person {}; 
class employee : public person {}; // bad idea: a person could have several job
                                  // or change job or (hopefully temporarily) without job

// possible alternative
class job_t { string title, company; date from,to; ... }; 
class person { vector<job_t> jobs; ... };  // very flexible 

在你的情况下,我知道Enclosure 有一些通用参数,但有一个形状因子(我称之为这个系列)决定了波如何与环境通信,以及其他一些功能。

在这种情况下,您可以选择:

class EnclosureFamily {
    public: 
       double compute_volume_in_room() = 0;  // abstract; 
}; 
class Enclosure
{    
    public:            //some common function
       double compute_volume_in_room() {
           return f->compute_volume_in_room();   // forwarding 
       }
    protected:
        int m_boxHeight;
        speaker *m_speakerBass; 
        EnclosureFamily *f;  // ok, but smart ponters should be preferred
}; 
class BoxEnclosure : public EnclosureFamily {
    public: 
       double compute_volume_in_room() { ... };  
};

这允许您根据需要更改机箱系列。顺便说一句,这是 strategy pattern 的实现。

如果你真的需要保留你原来的设计,你可以使用casting to parent并利用切片效果来覆盖父类:

*static_cast<Enclosure*>(BassReflex2Simu)= initialBox; // not forbidden but slicing

但是我不建议这样做(请记住,首先需要在父级上正确实施 3 规则)

【讨论】:

  • 好的,所以这是可能的但不是通用的,我需要在每个子类中添加一个指向通用参数的指针,因此如果有一天我向 parent 添加通用参数,我将需要更新手动所有子类。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-25
  • 1970-01-01
  • 1970-01-01
  • 2018-01-08
相关资源
最近更新 更多