虚函数

类的继承和派生(自我总结)

南笙酒味 提交于 2019-12-02 06:48:05
在派生类中: 无论是哪种继承都 不可以直接访问 上一级类继承下来私有成员 不可以直接访问 public protected 对于protect和public则根据继承方式的不同而不同, 继承方式的不同限制的是派生类对象对基类的访问 。 在派生类内部中: 无同名函数 可以访问除开基类私有成员的任何成员 有同名函数(同名就行) 派生类中的同名函数隐藏基类中的同名函数 可以通过类名::函数进行区分 可能会引发二异性(继承来的函数同名[同一等级]) protected继承与private继承的差别: protected不会继承到没有 —— private会继承到不能访问 只继承一次是看不出来差距的 类型转换 公有派生类对象(public方式) 可以被当作基类的对象使用,反之则不可以. 公有派生使得基类的对外访问接口是不变的 派生类的对象可以隐含转换为基类对象; 派生类对象可以初始化基类的引用 派生类的指针可以隐含转换为基类的指针 通过基类对象名、指针只能使用从基类继承的成员 不要重新定义继承而来的非虚函数 ,使得同名函数被覆盖掉,使用虚函数更加满足多态需求 派生类不能继承的基类成员 缺省构造函数,拷贝构造函数,拷贝赋值函数,以及析构函数这四种成员函数被称作特殊的成员函数 构造函数 未继承基类构造函数,那么使用派生类构造函数进行统一初始化 C++11规定: 可用using

类的多态

此生再无相见时 提交于 2019-12-02 06:47:59
运算符重载 不能重载的运算符 类属关系运算符“.” 成员指针运算符“.*” 作用域分辨符“::” 三目运算符“?:” 重载运算符 重载运算符函数必须要有重载的类在参数里面 成员重载运算符 调用时,必须是类对象进行调用,且会将自己自动传入做 this 双目运算符操作时,该类对象必须出现在左边,以进行调用 单目运算符操作时,int有是后置++/--,无是前置++/-- 非静态成员 #include using namespace std; class Clock { public: Clock(int hour = 0, int minute = 0, int second = 0); void showTime() const; Clock &operator++(); //前置单目运算符 Clock operator++(int); //int用于区分前置还是后置运算符 后置单目运算符 private: int hour, minute, second; }; void Clock::showTime() const{ cout 非成员运算符 用来解决调用对象不是类对象的情况(但参数还是要有类对象存在) 非成员 #include using namespace std; //非成员函数解决"复数+类"的情况,成员的运算符重载只能做到第一个参数是类类型的 class Complex

C++ 虚函数

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-02 06:40:58
1.虚函数: 用virtual定义的非static实例成员函数,虚函数可表现多态性,非虚函数的执行效率比较高,但是不能表现多态性; .虚函数总是有this,故参数后面可出现const 和 volatile,而staic成员函数无 this,故参数表后不可出现const 和 volatile,所以virtual 和 static 不能同时出现,否则关于this是矛盾的; 动态多态:重载函数表现的是静态(编译时)多态性,虚函数表现的是动态(运行时)的多态,多态一般指动态的编译; 重载函数是 静态多态函数 ,通过早期绑定调用重载函数,虚函数是动态多态函数,通过晚期绑定调用函数; 晚期绑定 是程序运行时由程序自己完成的, 早期绑定 是编译或者操作系统完成的; 虚函数的晚期绑定通过存储在对象中的一个指向虚函数入口 地址表 VFT的指针完成; 虚函数 一般 在基类的public或protected部分,在派生类中定义取代型函数时,函数原型必须和基类的虚函数必须完全相同;无论是否使用virtual保留字都将成为虚函数; 虚函数 只有 在具有继承关系的类称重才需要表现多态, union 既不能作为基类,也不能作为派生类,故 union 不能定义为虚函数; 构造对象 时类型是确定的,不需要根据类型不同表现为不同多态行为,故 构造函数 不能定义为虚函数; 析构函数 可通过父类指针

C++类与对象迷惑点

◇◆丶佛笑我妖孽 提交于 2019-12-02 02:52:28
类使用初始化列表以初始化字段 class Line { public: Line(double len); // 这是构造函数 private: double length; }; Line::Line( double len) { cout << "Object is being created, length = " << len << endl; length = len; } 等价于 Line::Line(double len): length(len) { cout << "Object is being created, length = " << len << endl; } 类函数前放置关键字 virtual,使成员函数继承父类定义的函数名称却实现不同功能,称之为多态。 虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。 纯虚函数在函数体处放置 = 0 以告诉编译器,函数没有主体,上面的虚函数是纯虚函数。 来源: https://www.cnblogs.com/WindyZ/p/11727167.html

override

天大地大妈咪最大 提交于 2019-12-01 23:10:43
描述:override保留字表示当前函数重写了基类的虚函数。 目的:1.在函数比较多的情况下可以提示读者某个函数重写了基类虚函数(表示这个虚函数是从基类继承,不是派生类自己定义的);2.强制编译器检查某个函数是否重写基类虚函数,如果没有则报错。 用法:在类的成员函数参数列表后面添加该关键字既可。 例子: class Base { virtual void f(); }; class Derived : public Base { void f() override; // 表示派生类重写基类虚函数f void F() override;//错误:函数F没有重写基类任何虚函数 }; 注意:override只是C++保留字,不是关键字,这意味着只有在正确的使用位置,oerride才启“关键字”的作用,其他地方可以作为标志符(如:int override;是合法的)。 来源: https://www.cnblogs.com/WHUT-Simon/p/11720516.html

Vtable内存布局分析

浪子不回头ぞ 提交于 2019-12-01 23:06:59
vtale 内存布局分析 虚函数表指针与虚函数表布局 考虑如下的 class: class A { public: int a; virtual void f1() {} virtual void f2() {} }; int main() { A *a1 = new A(); return 0; } 首先明确,sizeof(A)的输出是 16,因为:class A 中含有一个 int 是 4 字节,然后含有虚函数,所以必须含有一个指向 vtable 的 vptr,而 vptr 是 8 字节,8 + 4 = 12,对齐到 8 的边界,也就是 16 上述 class 的 AST record layout 如下: *** Dumping AST Record Layout 0 | class A 0 | (A vtable pointer) 8 | int a | [sizeof=16, dsize=12, align=8, | nvsize=12, nvalign=8] 可以证明对齐边界为 8 字节 需要注意的是:由于含有指针,而 64 位系统,指针为 8 字节,所以对齐边界是 8 虚函数表指针 vptr 为了完成多态的功能,现代的 C++编译器都采用了表格驱动的对象模型,具体来说,所有虚函数的地址都存放在一个表格之中,而这个表格就被称为 虚函数表vtable

c++语法笔记(下)

我的梦境 提交于 2019-12-01 17:21:25
多态性与虚函数 多态性 (函数重载,运算符重载就是多态性现象) 多态性 :向不同对象发送同一个消息,不同对象在接收时会产生不同的行为。(每个对象用自己的方式去响应共同的消息) 多态性又可以分为静态多态性和动态多态性 静态多态性 在编译时编译系统就可以判定调用哪个重载运算符(函数)。 #include<iostream> using namespace std; class point { public: point(float a, float b) { //构造函数 x = a; y = b; } friend ostream & operator <<(ostream &, point &); //运算符重载 protected: float x, y; }; std::ostream &operator<<(std::ostream &output, point &p) { //运算符重载的定义 output << "(" << p.x << "," << p.y << ")" << endl; return output; } class circle :public point { public: circle(float a, float b, float c) :point(a, b), radius(c) {} //构造函数 friend ostream

c++程序设计兼谈对象模型(介绍)

时光总嘲笑我的痴心妄想 提交于 2019-12-01 13:11:31
    主要介绍的内容为:泛型编程和面向对象编程 (1) 泛型编程和面向对象编程虽然分属于不同思维,但他们正是c++的技术主线,所以也将会记录template(模板) (2) 深入探索面向对象之继承关系所形成的对象模型,包括隐含与底层的this指针,vptr(虚指针),vtbl(虚表), virtual nechanism(虚机制)以及虚函数(virtual functions)造成的polymorphism(多态)效果。 来源: https://www.cnblogs.com/huahuati/p/11687768.html

空类,含有虚函数的类的大小

自作多情 提交于 2019-12-01 10:18:55
1、为何空类的大小不是0呢? 为了确保两个不同对象的地址不同,必须如此。 类的实例化是在内存中分配一块地址,每个实例都有独一无二的内存地址。空类也会实例化,为保证空类实例化后的独一无二性,编译器会给空类隐含的添加一个字节。所以,空类的sizeof为1,而不是0. 2、继承关系中的类大小: case 1: 父类有虚函数,子类继承。 class A{ virtual void f(){} }; class B:public A{} 此时,类A和类B都不是空类,其sizeof都是4,因为它们都具有虚函数表的地址。 case 2: 父类是空类,子类以虚基类方式继承。 class A{}; class B:public virtual A{}; 此时,A是空类,其大小为1;B不是空类,其大小为4.因为含有指向虚基类的指针。 case 3: 多重空类继承 class Father1{}; class Father2{}; class Child:Father1, Father2{}; 它们的sizeof都是1. 5、何时共享虚函数地址表: 如果派生类继承的第一个是基类,且该基类定义了虚函数地址表,则派生类就共享该表首址占用的存储单元。对于除前述情形以外的其他任何情形,派生类在处理完所有基类或虚基类后,根据派生类是否建立了虚函数地址表,确定是否为该表首址分配存储单元。 来源: https:/