写点什么

C++ 中的代码重用

作者:Maybe_fl
  • 2022-11-25
    陕西
  • 本文字数:1739 字

    阅读完需:约 6 分钟

C++中的代码重用


C++的一个主要目的是促进代码的重用,公有继承是实现这种目标的机制之一。本章介绍其他的方法,其中之一是使用类成员的方法,这种方法称为包含、组合或层次化,另外一种方法是使用保护继承私有继承

接口和实现

使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现)。获得接口的是 is-a 关系的组成部分。而使用组合,类可以获得实现,但不获得接口。不继承接口是 has-a 关系


举个例子

class Base{public:    void func() ;};
class Derived : public Base{ ...};
复制代码

公有继承继承接口,也就是说

Derived* pD = new Derived();pD->func();    //ok
复制代码

私有继承只继承实现,不继承接口

class Derived : private Base{    void func1()    {        ...        Base::func()        ...    }};
Derived* pD = new Derived();pD->func(); //error
复制代码


不继承接口,但继承实现。内部可以使用基类方法,但是外部无法使用。打个比方,汽车和发动机的关系,汽车并不是发动机,但是汽车需要使用发动机。这就是 has-a 关系

关键字 explicit

只用一个参数作为入参的构造函数将作为从参数类型到类类型的隐式转换函数,这通常不是我们期望看到的,使用explicit可以关闭隐式转换。


class Base{public:    Base(unsigned int x);};
复制代码


若没加 explicit 表示允许一个unsigned int转换为Base类型,如果这不是我们所期望的,请使用explicit修饰


class Base{public:    explicit Base(unsigned int x);};
复制代码


C++包含能让程序员限制程序结构的特性---使用explicit防止单个参数构造函数的隐式转换,使用const限制方法修改数据等等,这样做的根本原因是:在编译阶段出现错误优于在运行阶段出现的错误

私有继承

初始化基类组件

私有继承没有采用包含的方式,必须使用公有继承的技术,采用初始化列表的方式进行初始化


class Base{public:    Base(int x) ;};
class Derived : private Base{ Derived(int x, int y): Base(x){...};};
复制代码

访问基类的方法

使用私有继承时,只能在派生类中使用基类的方法,私有继承能够使用类名和作用域解析运算符来调用基类的方法,如之前的代码


class Derived : private Base{    void func1()    {        ...        Base::func()        ...    }};
复制代码

访问基类对象

如果期望在派生类中直接访问基类对象,使用强制类型转换可以达成。


const Base&  Derived::GetBase() const{    return (const Base&)*this;};
复制代码

访问基类的友元函数

答案还是强制类型转换,原因是友元函数使用静态联编

包含 or 私有继承?

包含也可以用来建立 has-a 关系,如果新类需要访问原有类的保护成员,或需要重新定义虚函数,则必须使用私有继承

保护继承

使用保护继承时,基类的公有成员和保护成员都将成为派生类的保护成员。基类的接口在派生类中也是可用的,但在继承层次结构之外是不可用的。当派生类再派生出另外一个类,私有继承和保护继承之间的区别便呈现出来了。

类模板

可以用模板参数来实现代码的重用


template <class T, int n>
复制代码


关键字class(此处与typename完全等价)指出 T 为类型参数


模板的具体化分为以下几种情况

隐式实例化

即声明一个或多个对象,指出所需的类型,而编译器使用通用模板提供的处方生成具体的类定义:


vector<int> vecArray;
复制代码


编译器在需要对象之前,不会生成类的隐式实例化


vector<int>* pvecArray;
复制代码

显示实例化

使用关键字telplate并指出所需类型来声明类时,会生成类的显示实例化。


template class ArratTP<string, 100>;
复制代码

显示具体化

显示具体化(explicit specialization)是特定类型的定义。有时候,可能需要在为特殊类型实例化,不使用通用的模板,对模板进行修改。


具体化类模板定义的格式如下


template <> class Classname<specialized-type-name> {...};
复制代码


举一个例子


template <> class vector<bool> {...};
复制代码


vector 实例化为bool对象时,直接使用一个byte保存一个元素即可,节约内存。

部分具体化

C++还允许部分具体化(partial specialization),即部分限制模板的通用性。举一个常用的例子,含有指针的类和不含指针的类有很大的区别。就可以为指针提供特殊版本来部分具现化现有的模板:


template <typename T>class vector {...};template <typename T*>class vector {...};
复制代码


用户头像

Maybe_fl

关注

还未添加个人签名 2019-11-11 加入

还未添加个人简介

评论

发布
暂无评论
C++中的代码重用_Maybe_fl_InfoQ写作社区