一、public 公有继承 - 示例分析 1、类型兼容性原则 类型兼容性原则 : C++ 的 " 类型兼容性原则 “ 又称为 ” 赋值兼容性原则 " ; 子类代替父类 : 需要 基类 ( 父类 ) 对象的...地方 , 都可以使用 " 公有继承 " 的 派生类 ( 子类 ) 对象 替代 , 该 派生类 ( 子类 ) 得到了 除 构造函数 和 析构函数 之外的 所有 成员变量 和 成员方法 ; 功能完整性 :..." 公有继承 " 的 派生类 ( 子类 ) 本质上 具有 基类 ( 父类 ) 的 完整功能 , 使用 基类 可以解决的问题 , 使用 公有继承派生类 都能解决 ; 特别注意 : " 保护继承 " 和..." 私有继承 " 的 派生类 , 是 不具有 基类 的 完整功能的 , 因为 最终继承 后的派生类 , 无法在 类外部调用 父类的 公有成员 和 保护成员 ; 2、类型兼容性原则应用场景 " 类型兼容性原则...子类对象 , 父类指针 值为 子类对象 在 堆内存 的地址 , 也就是 将 子类对象 地址 赋值给 父类类型指针 ; 引用 : 父类引用 引用 子类对象 , 将 子类对象 赋值给 父类类型的引用 ; 二
装饰的函数,现在是删除属性 del f1.flight_status f1.flight_status = "返航" 上面的3个装饰器分别是获取属性是使用的方法,设置属性时使用的方法、删除属性时使用的方法...实例是通过new来创建的。如果你想定制你的类,在实例化之前定制,需要使用new方法。说到继承,这里的写法和构造方法是一样的,可以先理解经典类的写法,比较直观。...新式类用super的写法参考之前的构造函数改一下也就出来了。 new方法必须要有返回值,返回实例化出来的实例。...使用经典类写法指定的话,可以return父类的new方法出来的实例,也可以直接将object的new出来的实例返回。但是这个返回值和构造并看不出有什么关系,为什么就触发了构造方法呢?后面会继续讲。...__init__,元类执行它的构造函数,创建了元类的一个实例,这里就是Foo类。然后再是通过 obj = Foo("Bob") 这个实例化的语句来触发了后面的一系列的结果。
,对内置类型不做处理,对自定义类型调用它的默认构造函数,规则和以前一样 派生类里面,把父类成员当做一个整体 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。...上面的修改确保当创建Student 类的对象时,它会首先调用 Person 类的构造函数初始化 _name,然后初始化派生类 Student 的 _num 成员 派生类这里分成了两个部分:父类和自己...派生类需要自己明确声明哪些函数或类是它的友元 如何解决编译错误: 要解决 Display 函数不能访问 Student 类的 _stuNum 成员的问题,可以在 Student 类中也声明 Display...,而不是与类的单个实例相关联。...每当创建一个 Person 类的实例或者它的派生类的实例时,构造函数都会递增 _count,因此 Student 和 Graduate 的示例也会递增 _count。
关键字 说明: 友元函数可访问类的私有和保护成员,但不是类的成员函数 友元函数不能用const修饰 友元函数可以在类定义的任何地方声明,不受类访问限定符限制 一个函数可以是多个类的友元函数...】(错误方式) 一.什么时候需要自己写拷贝构造函数?...默认生成的拷贝构造函数为:浅拷贝 需要自己写的情况: 自定义类型必须使用拷贝构造(深拷贝) 不需要自己写的情况 内置类型直接拷贝(浅拷贝/值拷贝) 例:Date类中都是内置类型,默认生成的拷贝构造函数为浅拷贝可以直接用...struct代替class) 三.函数模板的实例化 引入:用不同类型的参数使用函数模板时,称为函数模板的实例化。... 中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
返回新的对象 return Obj; 特点: 1.实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性 2.非常纯粹的继承关系,实例是子类的实例,也是父类的实例 3.父类新增原型方法...4.要想为子类新增原型上的属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中 构造函数继承 核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型...3.可以实现多继承,继承多个构造函数属性(call多个)。 4.在子实例中可向父实例传参。 缺点: 1.能继承父类构造函数的属性。 2.无法实现构造函数的复用。...4.实例并不是父类的实例,只是子类的实例 组合继承(原型链继承和构造函数继承)(常用) 核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用 function...2.每个新实例引入的构造函数属性是私有的。 3.既是子类的实例,也是父类的实例 缺点: 调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。 原型式继承 ?
而泛型编程则是将模板用特定的类型来实例化,例如将模板类 list实例化成真正的类 list。实例化代码是最终目的。 先学泛型编程再学元编程先学泛型编程再学元编程!...模板是基于用户为模板参数提供的参数在编译时生成普通类型或函数的构造。...只有我们实例化出模板的一个特定的版本时,编译器才会生成其对应的代码。当我们使用(而不是定义)模板时,编译器才会生成代码。这个特性影响我们如何组织代码以及错误何时才可以被检测到。...编译出现错误的时机: 第一阶段,编译模板本身时,该时期所出现的错误大多数为语法错误; 第二阶段,编译器遇到模板使用时; 第三阶段,模板实例化时,而只有在这个阶段才能发现类型相关的问题。...**注:**一个类模板的每一个实例都形成一个独立的类,而类模板的每个实例都有其自己版本的成员函数 所以,我们可能会出现一个单一模板并不能满足所有类型的需求,而模板特例化就出现了。
并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。...拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。 拷贝构造的特征: 拷贝构造函数是构造函数的一个重载形式。...拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。...但是还是存在特殊情况,对于类中的成员变量存在指针的时候就会出现问题,比如我们用类来实现一个栈,如果我们没有自己实现拷贝构造,那么在进行拷贝构造时,会按字节进行拷贝,会有两个数组指针指向同一块空间,由于析构函数会在程序结束时自动调用...友元的格式: friend ostream& operator<<(ostream& out, const string& str) 友元的特性: 友元函数可访问类的私有和保护成员,但不是类的成员函数。
对于基类中定义的静态成员,因为它属于基类类型,而不是基类对象,则在整个继承体系中只存在该成员的唯一定义。不论从基类中派生出来多少个派生类,对于每个静态成员来说都只存在唯一的实例。...不论 D以什么方式继承 B,D的成员函数和友元都能使用派生类向基类的类型转换;派生类向其直接基类的类型转换对于派生类的成员和友元来说永远是可访问的。...如果 D继承 B的方式是公有或受保护的,则 D的派生类的成员和友元可使用 D向 B的类型转换;反之,如果 D继承 B的方式是私有的,则不能使用。 就像友元关系不能传递一样,友元关系同样也不能继承。...基类的友元在访问派生类成员时不具特殊性,类似的,派生类的友元也不能随意访问基类的成员。但是基类的友元是可以访问内嵌在派生类对象中的基类成员。...派生类定义的构造函数与基类的构造函数具有相同的形参列表时,则该构造函数不会被继承,派生类中使用的是自己定义的相应函数。 默认、拷贝和移动构造函数不会被继承,这些构造函数按照正常规则被合成。
,其实都会报运行错误,注意是运行错误,而不是编译错误,只有在程序跑起来时,编译器才会报运行错误,语法检查上面,编译器认为你的这两个行为是合理的。...(这是规定,不要去考虑返回值较小寄存器带出这样的事情,只要返回就需要调用拷贝构造,和那个没关系) e. 为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。...4.赋值重载(是默认成员函数)和运算符重载(不是默认成员函数) 4.1 运算符重载(不是默认成员函数,需要自己写) C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型...,也可以选择给出缺省值,这样的两种情况都是可以进行隐式类型转换的, 2.多参数构造(C++11) 多参数构造在函数形式上就是多个参数没有给出缺省值,这倒是没有什么新颖的,但是在实例化对象时的使用方式就有些叫人眼前一亮了...友元函数可访问类的私有和保护成员,但不是类的成员函数 友元函数不能用const修饰 友元函数可以在类定义的任何地方声明,不受类访问限定符限制 一个函数可以是多个类的友元函数 2.友元类 友元类的所有成员函数都可以是另一个类的友元函数
组合通常是在希望新类内部具有已存在的类的功能时使用,而不是希望已存在类作为它的接口。组合通过嵌入一个对象以实现新类的功能,而新类用户看到的是新定义的接口,而不是来自老类的接口。...(has-a) 如果希望新类与已存在的类有相同的接口(在这基础上可以增加自己的成员)。这时候需要用继承,也称为子类型化。...那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误。 可是这个类的构造函数和析构函数都是私有函数了,我们怎样才能得到该类的实例呢?...非常遗憾的是,Try不是MakeFinal的友元,因此不能调用其私有的构造函数。...是MakeFinal的友元,因此该调用合法,所以try得以正确构造,而没有编译错误。
前者只能用于简记 已知类型,并不产生新的类型;后者则可以通过 函数模板返回值 等方法实现。尽管这两类模板不是必须的,但可以增加程序的可读性(复杂性)。...isBad, "neither Num nor Str"); } 代码编译时测试类型的错误用法 代码中的错误在于:编译代码的函数 ToString 时,对于给定的类型 T,需要进行两次函数绑定 —...一般思路是:提供两类重载 —— 一类接受 任意参数,内部 递归 调用自己;另一类是前者的 模板特化 或 函数重载,直接返回结果,相当于 递归终止条件。它们的重载条件可以是 表达式 或 类型。...元编程的主要难点 由于 C++ 语言设计层面上没有专门考虑元编程的相关问题,所以实际元编程难度较大。元编程的难点主要有四类:复杂性、实例化错误、代码膨胀、调试模板。...4.2 实例化错误 模板的实例化 和 函数的绑定 不同:在编译前,前者对传入的参数是什么,没有太多的限制;而后者则根据函数的声明,确定了应该传入参数的类型。
Blob{public:Blob();Blob(std::initializer_list i);}; 模板类的使用: 在定义类时,使用到类名的地方都需要显示的给出模板类的类型,格式为 int...类模板中的友元 一个类模板中也可以拥有友元(友元类/友元函数) 下面只有当与Blob类型相同的BlobPtr类和operator==函数才可以成为Blob模板类的友元 template <typename...//错误,Foo没有指出使用哪个模板实例化 类模板的static成员的特点:当一个类给出模板实例化之后,与这个类实例化类型相同的类共享一样的静态成员 Foo f1,f2,f3; //f1,f2...在此情况下,类和成员各自有自己的、独立的模板参数 演示案例 例如下面Blob是一个类模板,模板类型为T数据成员vector的类型也为T。...); //构造函数接受一个迭代器区间,用来初始化dataprivate:std::vector data;}; 现在我们在类的外部定义构造函数,由于类模板与成员函数都是模板,因此在外部定义时需要分别同时给出这两个模板的模板参数列表
类:完全可扩展的,除非显示的声明sealed 否则类可以继承其他类和接口,自身也能被继承注:虽然结构不能被继承 可是结构能够继承接口,方法和类继承接口一样 3.内部结构: 结构:没有默认的构造函数,...但是可以添加构造函数没有析构函数没有 abstract 和 sealed(因为不能继承)不能有protected 修饰符可以不使用new 初始化在结构中初始化实例字段是错误的 类:有默认的构造函数 有析构函数...执行时的行为:泛型也是对象,泛型类的“类型参数”变成了元数据;CLR会在需要的时候构造利用它们的类。一个泛型类经过编译好之后和普通的类并没有什么区别。编译的结果只有元数据和CIL。...以后,每次用一个引用类型参数来说实例化一个构造好的类型时,并在CIL中用Object引用替换类型参数,CLR都会重用以前生成好的泛型版本 09 9..NET BCL中有哪些泛型类型?...事件是用来阉割委托实例的,类比用一个自定义类阉割List。事件只能add、remove自己,不能赋值。事件只能+=、-=,不能= 。
和普通的类不同,这个圆括号不光可以写入构造函数的参数,还可以给类的属性赋值,在Obsolete的例子中,仅传递了构造函数参数。...你是不是要一个一个地去查看源文件,找出这些注释,再一条条插入数据库中呢? 通过上面特性的定义,我们知道特性可以用于给类型添加元数据,这些元数据可以用于描述类型。那么在此处,特性应该会派上用场。...那么在本例中,元数据应该是:注释类型(“更新”或者“创建”),修改人,日期,备注信息(可有可无)。而特性的目标类型是DemoClass类。...类的新实例,该布尔值指示是否将使用已过时的元素视为错误。...微软的软件工程师们就想到了这样的办法:不管是构造函数的参数 还是 属性,统统写到构造函数的圆括号中,对于构造函数的参数,必须按照构造函数参数的顺序和类型;对于属性,采用“属性=值”这样的格式,它们之间用逗号分隔
错误#3:无视“三法则” 什么是“三法则”? 三法则是,如果一个类定义了析构函数、复制构造函数或复制赋值运算符,那么它应该明确定义三个函数所有,而不是依赖它们的默认实现。...客户端通过构造函数在eth堆栈上创建了类a1的实例。然后他通过从a1复制创建了另一个实例a2。当a1超出范围时,析构函数将删除底层int *的内存。...因此,如果你的类只包含简单的数据类型,并且你计划使用隐式生成的移动构造函数,那么如果你定义复制构造函数则不可能。在这种情况下时,你必须显式定义移动构造函数。...你的错在于你让他们一开始就把自己的“脚”暴露给了友元类。 怎么解决? 避免在公共API类中使用friend。它们通常是设计不佳的表现,并且允许客户端访问API的所有受保护和私有成员。...错误#15:对外来(不是你自己的)对象类型使用前向声明 为什么这是一个错误? 对不属于你的API对象使用前向声明可能会以意外方式中断客户端代码。
对于下列成员变量,只能使用初始化列表进行初始化,因为这些成员变量只能在定义时就给出初始化的值: const成员变量 引用成员变量 没有默认构造函数的自定义类型成员 正确写法: class Date {...使用 explicit后,编译器会报错. 在C++中,关键字explicit用来修饰类的构造函数,它的作用是防止隐式类型转换。...当一个类的构造函数被声明为explicit时,编译器将不会自动执行隐式类型转换,而只能进行显式类型转换。这样会提高代码的可读性,隐式类型转换可读性不好....工具函数:静态成员函数可以作为工具函数,独立于对象的操作,提供一些辅助功能。 静态成员变量和静态成员函数为类提供了与类相关的特性和功能,并且可以在不创建类的实例对象的情况下进行访问和使用。...小结: 友元函数可访问类的私有(private)和保护(protect)成员,但友元函数不属于类,不是类的成员函数.
1.再谈构造函数 1.1 构造函数体赋值 构造函数是用来初始化对象的特殊函数。当我们创建一个对象时,编译器会自动调用构造函数来给对象的成员变量赋值。...总结:尽量使用初始化列表,因为它对自定义类型成员变量更高效。 1.3 explicit 关键字 构造函数不仅可以用来创建对象,还可以用来进行类型转换。...对于只有一个参数的构造函数,如果不使用 explicit 关键字,编译器会自动进行隐式类型转换。 简单理解:假设有一个银行系统,你有一个账户类。...3.3总结: 友元函数和友元类允许访问私有和保护成员,但要谨慎使用,因为这会增加代码的耦合性。 友元关系是单向的,不可传递。 使用友元可以解决一些特殊情况下的访问权限问题,如重载运算符等。 4....总结类和对象的关系 类 是对某一类实体的抽象和描述。类定义了这些实体具有的属性和方法,形成了一种新的自定义类型。 对象 是类的实例,是具体的实体。
image.png 现在,导入的 range 函数的类型为 any。这样做的好处是,将现有的 JS 项目迁移到 TypeScrip t可以减少编译时错误。...使用TypeScript 2.1,TypeScript 不是仅仅选择any类型,而是基于你后面的赋值来推断类型。 仅当设置了--noImplicitAny编译参数时,才会启用此选项。...混合类的构造函数 (如果有) 必须有且仅有一个类型为any[]的变长参数, 并且必须使用展开运算符在super(...args)调用中将这些参数传递。 定义完成之后,来研究一些代码。...比如, 有 X 为对象类型, new (...args: any[]) =X 是一个实例类型为 X 的混合构造函数类型。...这意味着咱们可以使用所有受支持的类功能,例如构造函数,属性,方法,getter/setter,静态成员等。
具体来说,下面这些会被标记为错误: 如果+运算符的任何一个操作数是可空的,并且两个操作数都不是any或string类型。...混合类指一个extends(扩展)了类型参数类型的表达式的类声明或表达式. 以下规则对混合类声明适用: extends表达式的类型参数类型必须是混合构造函数....混合类的构造函数 (如果有) 必须有且仅有一个类型为any[]的变长参数, 并且必须使用展开运算符在super(...args)调用中将这些参数传递。 定义完成之后,来研究一些代码。...比如, 有 X 为对象类型, new (...args: any[]) => X 是一个实例类型为 X 的混合构造函数类型。...这意味着咱们可以使用所有受支持的类功能,例如构造函数,属性,方法,getter/setter,静态成员等。
如果我们想要添加自己的行为,我们需要扩展框架的类或插入自己的类。...对于基于 setter 的 DI,容器将在调用没有参数的构造函数或没有参数的静态工厂方法来实例化 bean 之后调用我们类的 setter 方法。...Item item; } 在构造 Store 对象时,如果没有构造函数或 setter 方法将 Item bean 注入其中,容器将使用反射将 Item 注入 Store 中。...使用此方法很容易添加多个依赖项。如果我们使用构造函数注入,有多个参数会让我们认为这个类做了不止一件事,这可能违反单一责任原则。..." lazy-init="true" /> 因此,只有在第一次请求它时,才会初始化 item1 bean,而不是在启动时。
领取专属 10元无门槛券
手把手带您无忧上云