c++ --> 父类与子类间的继承关系

一、父类与子类

父类与子类的相互转换

1、派生类的对象可以赋给基类,反之不行

2、基类的指针可以指向派生类,反之不行

3、基类的引用可以初始化为派生类的对象,反之不行

4、派生类指针必须强制转换为基类指针后才可以指向基类

5、基类指针转换为派生类指针容易导致崩溃性错误

6、虚基类的引用或派生不能转换为派生类

class father{  //};
class son : public father{  //};
int main()
{
    father f;
    son s;
    f = s;//正确
    s = f;//错误

    father *pf = new son;//正确
    son *ps = new father;//错误

    father &rf = s;//正确
    father &rs = f;//错误
    return 0;
}

继承关系对基类成员的影响

  公有成员 保护成员 私有成员
公有继承 公有 保护 不可访问
保护继承 保护 保护 不可访问
私有继承 私有 私有 不可访问
成员函数 1 1 1
对象 1 0 0
子类 1 1 0

1:可以访问 0:不可访问

当所有成员都变成不可访问时,再往下派生就没有意义了

二、子类的构造与析构

1、构造派生类对象时,先执行基类的构造函数,再执行子类的构造函数,析构反之

class father
{
public:
    father(){cout<<"father construct"<<endl;}
    ~father(){cout<<"father delete"<<endl;}
};
class son : public father
{
public:
    son(){cout<<"son construct"<<endl;}
    ~son(){cout<<"son delete"<<endl;}
};
int main()
{
    son s;
    return 0;
}

输出:

father construct
son construct
son delete
father delete

2.如果是多重继承,基类的构造顺序按给定的顺序,析构反之

class father
{
public:
    father(){cout<<"father construct"<<endl;}
    ~father(){cout<<"father delete"<<endl;}
};
class mother
{
public:
    mother(){cout<<"mother construct"<<endl;}
    ~mother(){cout<<"mother delete"<<endl;}
};
class son : public father, public mother
{
public:
    son(){cout<<"son construct"<<endl;}
    ~son(){cout<<"son delete"<<endl;}
};
int main()
{
    son s;
    return 0;
}

输出:

father construct
mother construct
son construct
son delete
mother delete
father delete

3.利用基类的构造函数构造子类,效率更高

class father
{
    int x;
public:
    father(int a):x(a){cout<<"father construct:"<<x<<endl;}
};
class son : public father
{
    int y;
public:
    son(int a, int b):father(a), y(b){cout<<"son construct:"<<y<<endl;}
};
int main()
{
    son s(1, 2);
    return 0;
}

输出:

father construct:1
son construct:2

 

三、多重继承

1.多重继续的二义性,根本原因是

假如A有Test(),则B和C都有Test(),于是D产生了二义性

class A
{
public:
    void Test(){cout<<"A"<<endl;}
};
class B
{
public:
    void Test(){cout<<"B"<<endl;}
};
class C : public A, public B
{
};
int main()
{
    C c;
    c.Test();      //错误
    c.A::Test();   //正确,输出:A
    c.B::Test();   //正确,输出:B
    return 0;
}

2.编译器通常都是从离自己最近的目录树向上搜索的

子类的Test()覆盖了基类的Test(),并不代表基类的Test()消失,只是不能直接访问

class A
{
public:
    void Test(){cout<<"A"<<endl;}
};
class B
{
public:
    void Test(){cout<<"B"<<endl;}
};
class C : public A, public B
{
    void Test(){cout<<"C"<<endl;}
};
int main()
{
    C c;
    c.Test();      //正确,输出:C
    c.A::Test();   //正确,输出:A
    c.B::Test();   //正确,输出:B
    return 0;
}

3.对于单一继承,子类能否访问父类的父类,只与继承的方式有关

对于多重继承,子类不能直接访问父类的父类。

4.用virtual来避免二义性。

class B : virtual public A.

四、继承与包含

1.一个类的成员变量列表中包含另一个类的对象,叫做包含(包容)。

2.包含与私有继承的区别:

包含:

1)使程序看上去更清晰易懂

2)不存在继承带来的问题

3)可以包括另一个类的多个对象

私有继承:

1)可以访问基类的保护成员

2)可以重定义虚函数,实现多态

时间: 2024-10-26 22:56:55

c++ --> 父类与子类间的继承关系的相关文章

里氏替换原则:切忌按照常识实现类间的继承关系

什么是里氏替换原则 里氏替换原则(Liskov Substitution Principle LSP)定义为:任何基类可以出现的地方,子类一定可以出现. LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为. 为什么需要里氏替换原则 里氏替换原则看起来好像没啥了不起的,不就是继承要注意的一丢丢细节么,年轻人呐,你这样的思想很危险啊.事实上里氏替换原则常常会被违反,我在下面举例说明吧: 我们定义了一个矩形类:

Python中父类和子类间类属性(非实例属性)的设置获取的传递

前几天做一个项目,遇见类似这样一个问题.父类是个公用类,很多子项目中都运用到了,而子类也要作为一个基本类在该项目中的很多地方都要用到,但是的原始父类里面有些类属性(注意这里是类属性,不是实力属性).在程序运行时候要进行重新设置. 背景:Python中父类的类属性,类方法,实力属性都能够被子类继承,实力属性的再设置很简单,当然为了控制类属性的访问权限(Python中不能完全实现控制),也可以用@preproty装饰符优化和控制实力属性的设置,父类的类属性被子类继承,可以很容易的获得父类属性的内容,

$cast使用,父类与子类句柄(handle)的关系

?The handle of a child class can be assigned to a parent handle without any problem. ?Using $cast to assign the handle of a parent class to a child handle. class Parent; int m1 = 2; endclass class Child extends Parent; int m2 = 5; endclass initial be

验证当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行。

结果:当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行.

python 继承/父类和子类的关系

# <editor-fold desc="父类和子类关系,继承"># <editor-fold desc="类--讲解--Car"> class Car(): def __init__(self,make,model,year): self.make=make self.model=model self.year =year self.meter=0 def get_car_desc(self): long_name=str(self.yea

C++反汇编第三讲,反汇编中识别继承关系,父类,子类,成员对象

讲解目录: 1.各类在内存中的表现形式   备注: 主要复习开发知识,和反汇编没有关系,但是是理解反汇编的前提.     2.子类继承父类 2.1 子类中有虚函数,父类中有虚函数 : 都有的情况下    2.2 子类中没有虚函数,父类中有虚函数 : 子类没有,父类有的情况 2.1 2.2的情况都是一样的.     2.3   子类中有虚函数,父类中没有虚函数 : 子有父没有的的情况下    2.4 子类父类都没有虚函数的情况下 第二专题大总结. 熟悉反汇编可以直接看这个总结, 3.结合第二专题的

父类和子类关系/继承

#!/usr/bin/env python # -*- coding: utf-8 -*- """ @File:继承_子类和父类的关系.py @E-mail:[email protected] @Time:2020/4/4 12:39 上午 @Author:Nobita @Version:1.0 @Desciption:父类和子类关系/继承 """ class Car(): def __init__(self, make, model, year

hibernate继承关系映射关系方法(二)--每个子类一张表

TPS:所谓"每个子类一张表(Table Per Subclass)":父类一张表,每个子类一张表,父类的表保存公共有信息,子类的表只保存自己特有的信息 这种策略是使用<joined-subclass>标签来定义子类的.父类.子类都对应一张数据库表.在父类对应的数据库表中,它存储了所 有记录的公共信息,实际上该父类对应的表会包含所有的记录,包括父类和子类的记录:在子类对应的数据库表中,这个表只定义了子类中所特有的属性映射的字 段. person表 student表 work

1212面向对象--引用类型与值类型、命名空间与类库、继承(父类与子类)

五.引用类型与值类型 .NET将变量的类型分为值类型与引用类型.例如int和float之类的变量属于值类型,而“类“类型的变量属于引用类型. 值类型与引用类型的变量在使用上是有区别的. 值类型的变量在一定义之后就可以马上使用. 引用类型的变量定义之后,还必须用new关键字创建对象后才可以使用. 如上图,创建两个新的对象时,直接比较两个对象是否相等,返回的bool值为false.因为两个对象都是新开辟的一个空间变量,彼此没有任何关系,所有是不相等的. 如图2:1)创建的第一个新的对象ss1,给ss