函数默认参数和占位参数

1. 函数默认参数和占位参数(亚元) 形参中的占位参数又叫亚元,并没有什么实际意义,只在函数重载中起到作用 // 亚元,设置了默认值所以调用时可以不传参数 // 否则就必须传入两个参数 void foo(int a, int = 0){ cout << "a = " << a << endl; } int main() { foo(20); return 0; } 2. 函数重载 函数名相同,形参列表不同(形参个数、类型、顺序) 函数返回值不起作用 函数重载和默认参数不要同时使用(函数调用时容易产生二义性) 倾轧技术(name mangling),底层会将函数名进行编译 用 v c i f l d 表示 void char int float long double 及其引用 int fun(int) => fun_i int fun(int, char, double) => fun_icd 重载函数匹配顺序 如果能够严格匹配,则调用完全匹配的 如果没有完全匹配的,则调用隐式转换的 都匹配不上,编译失败 3....

December 26, 2021 · 1 min · Rick Cui

内存区间划分

一、程序运行前 代码区(只读的、共享) 数据区(全局变量和静态变量) 二、程序运行后 栈区 堆区 全局静态区(全局变量、静态变量、常量) 代码区 Linux程序运行内存虚拟地址空间: 三、全局变量与静态变量的区别 作用域不同 全局变量默认是 extern 的 静态变量是文件作用域 C/C++ 中 extern 关键字详解

December 26, 2021 · 1 min · Rick Cui

指针引用

指针也是一种变量,作为函数形参和返回值的时候也是值拷贝(拷贝的是一个地址) 使用指针引用的方式,代码更加简洁,逻辑更加清晰 释放掉指针指向的空间后,一定记得把指针置空 声明指针时就进行初始化或将其指向 NULL 是个好习惯 指针值拷贝: void test(int * a){ a = new int(20); //*a = 20; cout << "test point a = " << &a << endl; cout << "test:" << a << "\ta = " << *a << endl; } int main() { int *a = new int(10); cout << "main point a = " << &a << endl; cout << "main:" << a << "\ta = " << *a << endl; test(a); cout << "main:" << a << "\ta = " << *a << endl; return 0; } 输出:...

December 25, 2021 · 2 min · Rick Cui

抽象、封装、继承、多态

一、抽象、封装 数据抽象:是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制,是一种依赖于接口实现分离的设计技术 数据封装:是一种把数据和操作数据的函数捆绑在一起的机制 1. 好处 类的内部受到保护,不会因无意的用户级错误导致对象状态受损 类实现可能随着时间的推移而发生变化,数据抽象可以更好的应对不断变化的需求 2. 策略 通常情况下,我们都会设置类成员状态为私有(private),除非我们真的需要将其暴露,这样才能保证良好的封装性。 抽象把代码分离为接口和实现。所以在设计组件时,必须保持接口独立于实现,这样,如果改变底层实现,接口也将保持不变。在这种情况下,不管任何程序使用接口,接口都不会受到影响,只需要将最新的实现重新编译即可 3. 接口 接口描述了类的行为和功能,而不需要完成类的特定实现。如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类 设计抽象类(通常称为 ABC)的目的,是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象,它只能作为接口使用。因此,如果一个 ABC 的子类需要被实例化,则必须实现每个虚函数,如果没有在派生类中重写纯虚函数,就尝试实例化该类的对象,会导致编译错误。 可用于实例化对象的类被称为具体类 接口的好处实现了解耦合的作用。 可以将软件架构分为业务逻辑层、抽象层和实现层 二、继承 继承代表了 is a 关系。例如,哺乳动物是动物,狗是哺乳动物,因此,狗是动物,等等。一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。类派生列表以一个或多个基类命名 派生类可以访问基类中所有的非私有成员,同时,一个派生类继承了所有的基类方法,但下列情况除外: 基类的构造函数、析构函数和拷贝构造函数 基类的重载运算符 基类的友元函数 三、多态 虚函数:虚函数是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链编到该函数。我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链编,或后期绑定。 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数 一般要将父类的析构函数设置为虚函数,如果不把父类的析构函数设置为虚函数,在 delete 父类指针时就不会调用子类的析构了 类析构顺序:1)派生类本身的析构函数;2)对象成员析构函数;3)基类析构函数 若在基类中不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数,在函数参数后直接加 = 0 告诉编译器,函数没有主体,这种虚函数即是纯虚函数 测试类: // 基类 Shape class Shape { protected: int width, height; public: Shape(int a = 0, int b = 0) { width = a; height = b; } virtual ~Shape() { cout << "Shape destructor" << endl; } // pure virtual function virtual int area() = 0; }; // 基类 PaintCost class PaintCost { public: int getCost(int area) { auto res = area * 70; cout << "PaintCost: " << res << endl; return res; } }; class Rectangle: public Shape, public PaintCost { public: Rectangle(int a = 0, int b = 0):Shape(a, b) { } ~Rectangle() { cout << "Rectangle destructor" << endl; } void printPro() { // 访问父类的成员变量(不能访问父类的私有成员) cout << "width: " << width << "\theight: " << height << endl; } int area () { auto area = width * height; cout << "Rectangle class area: " << area <<endl; return area; } }; class Triangle: public Shape { public: Triangle(int a = 0, int b = 0):Shape(a, b) { } ~Triangle() { cout << "Triangle destructor" << endl; } int area () { auto area = width * height / 2; cout << "Triangle class area: " << area <<endl; return area; } }; 多继承:...

December 24, 2021 · 2 min · Rick Cui

类的静态成员

使用 static 关键字来把类成员定义为静态的。静态成员在类的所有对象中是共享的,当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本 如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零 不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化 如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数) 普通成员函数有 this 指针,可以访问类中的任意成员; class A { string name {"C++"}; int id {1024}; static int objCount; public: A(); friend void printA(const A &a); void printA(); static void printC(); }; // 静态成员类外初始化 int A::objCount = 0; A::A(){ objCount++; } void A::printA(){ cout << "objCount = " << this->objCount << "\tname = " << this->name << "\tid = " << this->id << endl; } void A::printC(){ // 静态函数内没有this指针 cout << "objCount = " << objCount << endl; // error: 'this' is unavailable for static member functions // cout << "objCount = " << this->objCount << endl; } void printA(const A &a){ cout << "objCount = " << a....

December 24, 2021 · 1 min · Rick Cui