个人知识库 个人知识库
首页
关于
  • C语言
  • CPlusPlus
  • Linux
  • PHP
  • Nginx
  • MySQL
  • Redis
  • Docker
  • Kubernetes
  • SRS
阅读
常用工具
  • 分类
  • 标签
  • 归档
GitHub

Agnes001

坚持是一件很伟大的事业
首页
关于
  • C语言
  • CPlusPlus
  • Linux
  • PHP
  • Nginx
  • MySQL
  • Redis
  • Docker
  • Kubernetes
  • SRS
阅读
常用工具
  • 分类
  • 标签
  • 归档
GitHub
  • C语言

  • CPlusPlus

    • 基础特性

      • 枚举
      • 字符指针
    • vs2019设置
    • C++11特性

    • 并发编程

    • 引用
    • 类和对象
    • 友元和运算符重载
    • 继承
    • 继承和多态
      • 1 类与类的关系
        • 1.1 继承(inheritance) 表示 is-a
        • 1.2 组合 (composition) 表示has-a
        • 1.3 委托 (delegation) 表示composition by reference
      • 2 继承
        • 2.1
        • 2.2 虚函数
        • 2.3 纯虚函数
        • 2.3 虚继承
      • 3 多态
        • 3.1 多态的实现原理
      • 4 衍生出的设计模式
        • 4.1 单例模式
        • 4.2 观察者模式
    • 模板
    • C++基础总结
    • 类型转换
    • 异常
    • 容器
    • 算法
    • C++程序设计
    • C++ Primer总结
    • 编程技巧
    • 标准库体系结构与内核分析
    • 设计模式
    • cmake配置C++工程
    • libcurl的使用总结
    • web开发框架--drogon
    • log4cplus使用
    • C++数据类型
    • 函数
    • 线程
    • 进程
    • 文件操作
    • 日常问题记录
    • Cpp案例程序
    • 多线程
    • 侯捷c++11新特性
    • 侯捷stl
  • Lua技术栈

  • edoyun

  • 内存管理

  • 数据结构

  • 网络编程

  • Linux

  • 池化技术

  • 操作系统

  • python

  • 编程技术
  • CPlusPlus
Agnes001
2022-01-02

继承与多态

# 1 类与类的关系

# 1.1 继承(inheritance) 表示 is-a

父类和派生类被称为继承。

class _List_node_base{...}; // base class 

class _Lisr_node: public _List_node_base {...} // derived class 

# 1.2 组合 (composition) 表示has-a

类中包含另一个类的对象,所占空间累加在当前对象上

template <class T, class Sequence = deque<T>>
class queue {
...
protected:
Sequence c; // 底层容器
public:
// 以下完全利用 c 的操作函數完成
bool empty() const { return c.empty(); }
size_type size() const { return c.size(); }
reference front() { return c.front(); }
reference back() { return c.back(); }
// deque 是兩端可進出,queue 是末端進前端出(先進先出)
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_front(); }
};

构造由内而外,析构由外而内:构造时先调用里边对象的构造函数,然后再调用当前类的构造函数,析构时正好相反。

非共有继承也是一种has-A的组合方式,非公有继承中,子类不能转化为父类,因为创建父类指针指向子类对象的时候,会调用子类构造函数,再调用父类构造函数,但此时父类构造函数的访问权限是非共有的,因此访问不到父类的构造函数,即无法用这种方式创建对象。主要在基类中没有普通成员属性的时候使用这种继承方式,可以减少内存占用。

# 1.3 委托 (delegation) 表示composition by reference

类内含有另一个类的指针。

class StringRep;
class String
{
public:
	... // 一些公有接口
private:
	StringRep* rep; //类内含有类的指针
}

class StringRep{...};

组合与委托的区别

  • 组合生命是一起出现的,有queue对象就有了deque对象。
  • 而委托,类内含有指针,只有需要用到类指针的时候才会有指向的实现类,不同步。

# 2 继承

单继承:同时有多个父类 多继承:只有一个父类

# 2.1

# 2.2 虚函数

在基类和派生类对应的函数前添加virtual关键字。 override关键字 派生类可以在它覆盖的函数前使用virtual关键字,但不是非得这么做。C++11中,允许显示注明它使用某个成员函数覆盖了它继承的虚函数,在函数后添加关键字override,这样做的好处是,使得程序员的意图更加清晰的同时,还可以让编译器发现一些错误。

与重定义进行区分: 重定义:派生类的函数屏蔽了与其同名的基类函数,规则如下:

  1. 如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。
  2. 如果派生类的函数与基类的函数同名,并且参数也相同,但是基函数没有virtual关键字,此时,基类的函数被隐藏。
class A {
public:
	A() { cout << "A constructor" << endl; }
	virtual ~A(){}
	virtual void test() { cout << "A test()" << endl; }
};
class B : public A {
public:
	B() { cout << "B constructor" << endl; }
	virtual ~B() {}
	void test(int a) { cout << "B test(int)" << endl; }
};
int main(){
  B* pB = new B;
  pB->test();//error : 函数中调用的参数太少,因为此时基类的函数被隐藏.
}

# 2.3 纯虚函数

virtual void test() = 0; 一个具有纯虚函数的基类称为抽象类.

# 2.3 虚继承

菱形继承(继承路径上有一个公共的基类),会产生二义性,公共基类会在派生类的对象中产生多个基类子对象,为了解决以上问题,必须对这个基类声明为虚继承,使这个基类成为虚基类。

class A{public: int a;};
class B : virtual public A{public: int b;};
class C : virtual public A{public: int c;};
class D : public B, public C{public: int d;}
//调用类的顺序为:A-B-C-D

虚继承会生成虚基表和虚基表指针。 虚继承的内存结构 虚继承的内存结构和普通继承的内存结构是不同的,虚基类会在子类结构中被整合到后部。 上述案例中的内存结构为

内存 数据
ec0 B类虚基表指针
ec8 b
ed0 C类虚基表指针
ed8 c
ee0 d
eec a

具体情况可写代码进行测试

# 3 多态

动态绑定只有通过指针或引用调用虚函数时才会发生。 当通过一个具有普通烈性(非引用非指针)的表达式调用虚函数时,在编译时就会将调用的版本确定下来。

# 3.1 多态的实现原理

当类中声明虚函数时,编译器会在类中生成一个虚函数表,虚函数表时一个存储类成员函数指针的数据结构,虚函数表时由编译器自动生成与维护的.

声明在内层作用域的函数不会重载声明在外层作用域的函数。

# 4 衍生出的设计模式

# 4.1 单例模式

# 4.2 观察者模式

委托+继承

class Subject{
  int m_value;
  vector<Observer*> m_views;
public:
  void attach(Observer* obs){
    m_views.push_back(obs);
  }
  void set_val(int value){
    m_value = value;
    notify();
  }
  void motify(){
    for(int i = 0; i < m_views.size(); ++i){
      m_views[i]->update(this, m_value);
    }
  }
};
class Observer{
public:
  virtual void update(Subject* sub, int value) = 0;
};
编辑此页
#inheritance
继承
模板

← 继承 模板 →

Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式