C++把子类对象当基类对象使用

★当公有继承的时候,子类对象可以当基类对象来使用。

①把一个子类对象赋值给基类对象;
例:
 class Base;
 class Derived:public Base;

 Derived d;
 Base b;

 b=d;  //OK,子类可以赋值给基类(把子类的基类部分赋值给基类);
 d=b;  //ERROR,基类不可以赋值给子类(子类中含有自己的附加部分,而基类没有);

②基类引用引用一个子类对象;

a.用子类对象初始化一个基类引用;
例:
 Base &b=d;

b.子类对象被用作函数的参数,这个参数接受一个基类的引用;
例:
 func(Base& b);
 func(d);

c.返回值是一个基类的引用却返回了一个子类;
例:
 Base& func(){return d;}

▲当基类引用引用子类的时候,表现的是基类的行为。或者说定义在子类的成员和成员函数不能被基类进行访问。

例:
 Base &b=d; //b是子类对象,但是b的行为是基类行为(只能调用子类继承来的基类部分的方法,不能调用子类附加部分的方法);

▲特殊情况下,假如子类覆盖了基类的某些函数,引用时依然调用基类的函数。
例:
 class Base
 {
 public:
  func(){cout<<"b"<<endl;}
 };
 
 class Derived:public Base
 {
 public:
  func(){cout<<"d"<<endl;}
 };

 Base& b=d;
 b.func(); //调用Base类的func()方法;

▲函数在接受一个基类引用或者返回一个基类引用,其依然表现基类行为(不能访问子类的附加部分);
例:
 fun(Base& b){
   b.fun();
   }
 fun(d);  //调用Base类的func()方法;
 
▲拷贝构造可以接受一个基类引用,但是我们可以引用一个子类对象,拷贝构造出口来的还是一个基类对象;
例;
 Base(const Base& b);
 Base b1(d); //拷贝构造出来的b1是一个基类对象;

▲传值;
例:
 func2(Base b){
   b.func();
   }
 
 func2(d) //传值调用拷贝构造,结果构造了一个基类对象;

▲返回值;  //返回基类;
例:
 Base func3(){
   return d; 
   }

③基类指针可以指向一个子类对象;

a.子类地址赋值给基类指针;
例:
 Base* p=&d;

b.子类指针赋值给基类指针;
例:
 Base* b;
 Derived* d;
 b=d;

c.子类对象传递给函数;
例:
 func(Base* b);
 Derived d;
 func(&d);

d.子类地址返回,函数返回基类指针;
例:
 Base* func();
 func(){return d;}

***可以用一个基类指针引用一个子类指针,这种情况经常发生在函数传参;

***以通过基类指针还是基类指针的引用,这时还是基类行为,指向一个子类对象;

★基类对象不能当子类对象使用(因为基类对象没有子类对象的附加部分)。然而一个基类指针指向一个子类对象,表现出基类行为。
例:
 Base* b=&d;
 b.func(); //输出b;
 static_cast<Derived*>(b).func()  //静态强制转化,输出d;
 (Derived*)b.func()   //同上;


★基类指针可以转换成子类指针(很危险,最好不用)。要保证不出错需要基类的指针指向子类的对象的地址,或者基类对象是子类对象的引用。
例:
 Base* b;    //基类的指针指向子类对象的地址;
 Dericed d;
 b=&d;
 (Derived*)b->fun();

 Base& b=d;    //基类对象是子类对象的引用;
 b.fun();
 ((Derived&)b).fun()


★总结:
 基类不能以任何形式赋给子类。传递啥无所谓,看定义的是啥类型就是啥类型,叫表现啥类型的行为。(虚函数不适用)

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C++中,子类和类之间的转换可以通过类型转换实现。在进行子类和类之间的转换时,需要注意以下几点: 1. 子类对象可以直接转换为对象,因为子类对象中包含了对象的所有成员。 2. 对象不能直接转换为子类对象,因为对象中不包含子类对象的成员。如果需要将对象转换为子类对象,则需要使用强制类型转换,但这种转换可能会导致编译错误或运行时错误。 3. 在进行子类和类之间的指针转换时,可以使用dynamic_cast操作符进行安全转换。dynamic_cast操作符可以检查转换是否合法,如果转换不合法,则会返回空指针。 示例代码如下: ```c++ class Base { public: virtual void foo() { cout << "Base::foo() called" << endl; } }; class Derived : public Base { public: void foo() override { cout << "Derived::foo() called" << endl; } }; int main() { // 子类对象可以直接转换为对象 Derived d; Base &b = d; // 对象不能直接转换为子类对象 Base b2; // 编译错误:invalid static_cast from type 'Base' to type 'Derived&' // Derived &d2 = static_cast<Derived &>(b2); // 使用dynamic_cast进行安全转换 Base *pb = new Derived(); Derived *pd = dynamic_cast<Derived *>(pb); if (pd) { pd->foo(); // Derived::foo() called } else { cout << "dynamic_cast failed" << endl; } delete pb; return 0; } ``` 在上面的示例代码中,定义了一个类Base和一个子类Derived,其中子类继承了类。在main函数中,首先将子类对象d转换为对象b,然后尝试将对象b2转换为子类对象d2,但这个转换是不合法的,会导致编译错误。接着定义了一个类指针pb,将其指向子类对象,并使用dynamic_cast将其转换为子类指针pd,如果转换成功,则调用子类的foo方法,否则输出转换失败的信息。最后记得释放动态分配的内存。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值