【问题标题】:C++ - Copying of objects of derived class into objects of base classC++ - 将派生类的对象复制到基类的对象中
【发布时间】:2013-08-11 18:27:26
【问题描述】:

由于重载运算符=的限制,我们不能将派生对象复制到基类的对象中。那么,为什么我们可以将派生对象的地址复制到基类的指针中呢?不应该反过来,因为派生对象的大小比基类对象大。事实上,当我尝试它时,我得到了一个错误,上面写着the conversion of a base object to the derived object is not allowed。你能告诉我为什么吗?我无法在互联网上找到任何相关信息。 代码如下:-

#include<string>
#include<vector>
#include<iostream>
using namespace std;
class employee
{
    protected:
        string name;
        double pay;
    public:
        employee(string ename,double payRate)
        {
            name = ename;
            pay = payRate;
        }
        virtual double GrossPay(int days)
        {
            return pay*days;
        }
        virtual string getName()
        {
            return name;
        }
};
class manager:public employee
{
    private:
        bool salaried;
    public:
        manager(string ename,double payRate,bool isSalaried):employee(ename,payRate)
        {
            salaried = isSalaried;
        }
        virtual double GrossPay(int days)
        {
            if(salaried)
                return pay;
            else
                return pay*days;
        }
};
int main(void)
{
    employee* emp2;
    employee emp3("Bill",350);
    manager mgr3("Alice",200,true);
    emp2 = &emp3;
    cout<<emp2->getName()<<" earns "<<emp2->GrossPay(40)<<endl;
    emp2 = &mgr3;
    cout<<emp2->getName()<<" earns "<<emp2->GrossPay(40)<<endl; // The code works till here
    //The problematic part starts from here:- 
    manager* mgr6;                                          
    employee emp5("NewBill",300);
    mgr6 = &emp5;
    cout<<mgr6->getName()<<" earns "<<mgr6->GrossPay(40)<<endl;
    return 0;
}

注意:我显示的错误是编译器实际显示的简化。

【问题讨论】:

  • 我不确定我是否理解正确。你可以做 - Base obj = Derived();。但是,对象被切片。请发布您尝试过的测试程序。
  • 你问为什么不能分配Derived* obj = (Base*)whatever?它与大小无关,因为指针的大小都相同。它必须这样做,您不能保证 (Base*) 指向派生对象,它可以是任何其他派生类。
  • @MadScienceDreams “指针大小都一样” 实际上,这不能保证是真的。标准不需要这个。 (例如分段内存模型的远近指针)
  • @milleniumbug 哇...+1 你每天都学到新东西...有时我很高兴我学会了编程,因为它变得更简单了,有时我认为它只是让我成为一个相对草率的程序员.

标签: c++ inheritance


【解决方案1】:

您无法将基础对象转换为派生对象,因为没有足够的信息。这就像吃了一个空三明治并假装它是 BLT!

向下转换对象的问题是派生类可能更大,因此不适合可用内存,但指针是允许的,因为派生类完全是基类,而且更多。继续三明治的比喻:如果忽略馅料,BLT 只是一个空三明治。

在您的示例中,mgr6 认为它指向 manager,但说有一个用于 bool salaried 的吸气剂,称为 IsSalaried(),如果您调用 mgr6-&gt;IsSalaried(),会发生什么情况。这显然不合逻辑,因此是不允许的。

【讨论】:

    【解决方案2】:

    继承关系通常被描述为“Is A”,例如,如果您有一个 Vehicle 基类和两个派生类 MotorCycle 和 Semi,那么

      Motorcycle *m = new Motorcycle();
      Semi *s = new Semi();
    
      Vehicle *v1 = m;
      Vehicle *v2 = s;
    

    很好。摩托车是车辆,半是车辆。 您可以在 v1 和 v2 上调用任何您想要的方法,并且会有该方法的实现。

    另一方面,如果你说:

      Motorcycle m2 = v2;
    

    你会有麻烦的。车辆(不一定)不是摩托车。

    假设 Motorcycle 类有一个名为 wheelie() 的方法,它不在 Vehicle 类中(出于显而易见的原因)在分配之后你可以说: M2->wheelie();

    而你那可怜的半身人不知道该怎么做。因此从基类到派生类的强制转换是不合法的。

    【讨论】:

    • 如果您启用了 RTTI,那么您可以使用 运算符从车辆投射到摩托车。它将检查对象的实际类型,如果转换无效则失败。
    【解决方案3】:
    manager* mgr6;                                          
    employee emp5("NewBill",300);
    mgr6 = &emp5;
    

    在您的示例中,manager 类派生自 employee 类。所以,emp5 是一个基类对象。它不知道派生类的成员。

    mgr6manager * 类型,它试图指向emp5。如前所述,emp5 没有派生类子对象供赋值操作工作。

    但是,这行得通。

    employee* emp2;
    manager mgr3("Alice",200,true);
    emp2 = &mgr3;
    

    因为,mgr3 同时拥有派生类和基类子对象。

    编辑:在最后一行将 emp3 更正为 mgr3

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-26
      相关资源
      最近更新 更多