Fucking in c++第十三章笔记
1、组合就是由类成员(或称成员类)组成新类
2、继承实际上也是由基类做子成组成新类,但语法上有不同,体现了OOP的思想
基类在继承类中默认是私有的,以Y:public X形式继承则变为公有。
从继承类的外部调用基类的任何成员都要加上基类名,如Y y; y.X::f( ); 而对于成员类则要加上对象名y.x.f( );
3 由于C++强制初始化,因此基类和成员类都必须在新类的构造函数初始化列表中初始化
初始化语法:对于基类,使用类名调用构造函数;对于成员类,使用对象名调用构造函数,如Y::Y(int i):X(i), x(i) {}
4 继承类默认继承了基类的成员函数,即,在不重定义的前提下,y.f( )和y.X::f( )调用的同一个函数
而组合类则必须通过成员类对象进行函数调用
继承类和组合类的构/析造函数调用次序相反,前者从基类到子类5 如果重定义了基类的函数,则基类的同名函数全部自动隐藏。
所谓“全部”是因为,可能在基类中有多个同名的重载函数,它们全部隐藏
所谓“隐藏”不是说不能调用,而是说,当调用y.f( )时调用的是Y中定义的新f( ),想调用基类的f则要显式说明y.X::f( )
6 所有构造函数、析构函数、operator=都不能自动继承
但编译器会自动生成默认构造函数、拷贝构造函数、operator=,并正确地调用基类的相应函数,它们工作的很好
自动类型转换函数会自动继承
如果想让编译器自动创建子类的默认构造函数,我们就不能为子类定义任何(包括拷贝)构造函数。这和普通类的规则是一样的
但是如果不为子类定义任何构造函数,则只能使用自动生成的默认和拷贝构造函数
因此,如果想为子类定义带参数的构造函数,则必须同时也定义子类的默认构造函数
如果自定义了拷贝构造函数,则也必须同时自定义默认构造函数
在子类的默认构造函数中,如果想调用基类的默认构造函数,无需显式调用
在子类的拷贝构造函数中,如果想调用基类的拷贝构造函数,必须显式在初始化列表调用,否则自动调用默认构造函数
在子类的operator=中,如果想调用基类的operator=,必须显式在函数体中调用,否则编译器什么也不做
8 静态成员函数的继承规则和非静态成员函数一样,只是static成员函数不能是virtual
9 所以最好的方案是:
如果不定义带参数的构造函数,就什么都不要动,编译器自动生成符合要求的默认/拷贝构造、析构、operator=
如果必须定义带参构造函数,就要同时定义默认构造函数,但定义时无需显式调用基类默认构造函数
没事就不要自定义拷贝构造函数和operator=,如果一定要重定义,必须显式调用基类的拷贝构造函数和operator=
10 可以看到,组合类和继承类的编译器实现是一样的
到目前为止,两者区别在于继承类继承了基类的函数接口,继承是is-a关系,组合是has-a关系
C++默认是私有继承,即此时并不能直接通过子类对象调用基类函数(即y.X::f()),而要在Y内用using X::f;
11 protected的意义是仅自己和子类可以访问自己的成员,外部不可访问
private-protected-public的关系很像linux中文件权限的owner-group-others的关系
也可以protected继承,但通常没有应用实例,它的存在只为语言的完备性
12 除operator=之外的所有基类运算符都会自动继承,但它们操作的都是子类中“基类的成员”
,即,如果X和Y都有int成员i,则Y y;++y;加的是X中的i,而不是y中的i;同理operator==的意义也不会检测y中的i
13 C++支持多重继承,但作者认为多重继承总可以转化为单重继承,并且多重继承很难掌握,因此不建议使用。
14 继承和组合的优点之一是支持渐进式开发。程序员应当更多关心处理数据关系,而不是进行具体的位操作
15 子类可以自动向上类型转换为基类,这对于类本身、类指针、类引用都有效
在编译器自动生成的子类拷贝构造函数中,首先执行基类拷贝构造函数,之后按声明顺序执行成员类拷贝构造函数
多重继承可以通过组合类的形式代替
指针和引用被自动向上类型转换之后,子类的成员会不能访问,这将通过下一章的virtual函数解决
////////////////////////////////////////
Copyright @ 炮灰九段 Powered by: .Text and ASP.NET Theme by: .NET Monster