lingshi c++ 笔记

c++学习

(01)使用传统的有参构造函数,在构造函数内部进行变脸过的赋值;

(02)使用构造函数初始化列表进行初始化:构造函数后面+(:属性(参数),属性(参数)… ;

//需求:创建类中的对象并且保证只有一个这样的对象实例

class printer {

private:

printer() {}

printer(const printer &p);

public:

static printer * get_instance() {

return single_printer;

}

private:

static printer* single_printer;

};

printer *printer::single_printer = new printer;

 

void test01() {

//拿到打印机

printer * printer_ = printer::get_instance();

}

ostream & operator<<(ostream &cout, my_string &str) {

cout << str.p_string;

return cout;

}

//声明

template<class nametype, class agetype >class person;

template<class nametype, class agetype>void do_work(person<nametype, agetype> &p);

    父类和子类之间的转换:向下转换不安全,向上转换安全;(父类所维护的空间比子类小)

父子转子不可以,子转父可以,在发生多态的情况下都可以转换;

  • 常量转换:只对指针或者引用有效,
  • 动态类型转化:     基础数据类型不可以转换;
  • 静态类型转换:基础数据类型:使用static_cast<要转换的目标类型>(要转换的数据);
  • 多态就是父类的指针或者引用指向子类;
  • 菱形继承:解决父类身上的多个同属性成员的二义性继承和空间浪费,使用虚基类(虚基类指针和虚基表,通过表找到偏移量,找到共享数据);
  • 动态联编:如果是全局函数传参为继承中的父类或者子类,此函数会静态联编(在编译时期进行早绷定,也无法使用作用域进行区分),需要把函数重调用的类中的方法声明为虚函数,进行晚绷定即在运行调用时选择要传入的参数;(即父类的引用或指针 指向子类时使用多态);
  • 多态有利于后期的扩展,可读性高,缺点是效率低一点;
  • 父类中有纯虚函数,那么父类无法实例化对象,子类继承父类必须要实现纯虚函数;
  • 虚析构用来解决父类指针指向子类时,释放空间不彻底的问题
  • 纯虚析构函数,需要在类内声明,类外实现,包含纯虚析构函数的类是抽象类;
  • 普通函数可以进行隐式类型转换,函数模板不可以;
  • c++编译器优先考虑普通函数;可以通过空模板实参列表<空参数>的方式限定编译器只能通过模板匹配;函数模板可以像普通函数一样进行重载;
  • 模板不能解决所有的类型;可以通过具体化来解决:template<>返回值 函数名<具体类型>(参数)
  • 类模板不是类名不确定,而是类中的成员的类型不确定;
  • 类模板并不能进行自动类型推导,需要进行显式的指定类型;
  • 类模板可以指定默认的类型参数:class T = int;
  • 子类继承父模板类,必须指定出父模板类的类型,否则,子类无法分配内存;
  • 模板类中友元函数的类外实现需要时,01)类中的友元声明中需要加入<>空参数列表到声明中,如:friend void do_work<>(person<nametype, agetype> &p);//只是普通的函数的声明,需要使用空参列表强制使用模板函数  02)需要在整个类前声明类和友元函数;如:
  • 子类会继承父类的私有成员,只是被编译器隐藏,无法访问;
  • 构造函数调用顺序:子类——》父类,析构函数调用正好相反,并且子类不会继承父类中的构造和析构函数;
  • 如果父类中没有默认构造函数,子类可以通过初始化列表显示的调用父类的其他构造函数;
  • 继承中同名函数的调用默认使用就近原则,除非使用如:son.base::L_value这种方式显示的区分调用父类中的同名函数;也就是加上父类的作用域;
  • 静态成员函数:可以通过类名(作用域)直接访问公有静态成员函数,也可以通过对象访问公有静态成员函数;
  • 只有非静态成员变量才属于对象;
  • 成员变量和成员属性是分开存储的;
  • 空类的大小为1,使用char维护类地址;
  • this指针指向被调用的成员函数所属的对象;
  • 如果成员函数没有用到this,那么空指针可以直接访问到,如果成员函数用到this指针,要注意判断对象指针是否为空;
  • 常函数  void func() const{},修饰的是this指针 ,const type* const this;,不能修改this指针指向的值;
  • 常对象,在对象前加入const修饰对象,不可以调用普通的成员函数,能调用常函数;
  • 使用(.hpp)调用外部模板文件;
  • 对于+运算符的重载,使用(operator+)进行重载;
  • 使用全局函数实现+运算符的重载,需要手动实现运算符重载函数的内容;在使用时直接person p2 = p1+p3;
  • 对于运算符的重载:运算符重载只能重载基本的数据类型,对于自定义的数据类型,需要手动实现重载函数;
  • 左移运算符的重载只能使用全局函数定义;void operator<<(参数一是ostream;参数二是要打印的数据类型);
  • 类对象也可作为成员;
  • explicit关键字防止隐式类型转换;
  • 建立类对象数组:Person * pArray = new Person[10];通过new(也就是堆区)开辟数组一定会调用构造函数;所以一点更要提供默认构造;使用delete[]person;释放;
  • 静态成员变量会共享数据,在类内声明,类外实现;
  • 静态成员函数可以在类内实现,不可以访问普通的成员变量(静态成员函数无法区分是哪个对象的成员) ,可以访问静态成员变量(静态成员变量是共享的,只有一份);
  • 单例模式:一个类只可以实例化出一个对象;
  • 单例模式原理:利用私有static静态成员变量的的唯一性,定义一个私有的静态成员指针指向内部实现的对象;在提供一个接口在类内部返回这个私有的指向对象的指针;详细如下:
  • 当一个函数体的内部需要改变实参的值时,则需要使用指针参数。qq.com
  • 函数调用时实参值将复制到形参中。
  • 当const出现在*号左边时,指针指向的数据为常量
  • 当const出现在*号的右边是时,指针本身为常量
  • c++ new 出来的对象需要用指针指向
  • 子类从父类继承过来的函数可以按照需求重写
  • 父类指针可以指向子类 如:perent *p = new child(); ()是用来给构造函数传参的
  • inline函数,为了解决简单而又频繁调用的函数反复的压栈出栈的操作冗余,相当于宏函数,省去了压栈出栈的操作
  • 函数指针定义方法之第三种:int myfucn(){/*/*/*/*/*/},int"函数返回类型"(*pointer_name)(“函数的形参”) = NULL;pointer_name = myfunc;
  • 函数指针不能发生重载,因为指针指向的函数地址不同。
  • 对于拷贝构造函数,如果不写会自动调用默认的拷贝构造函数,如果写可以自定义拷贝构造函数
  • 构造函数是对象初始化的时候调用的
  • 当自己提供了有参构造函数,系统不会再提供默认无参构造函数,但依然会提供拷贝构造函数;
  • 当自己提供了拷贝构造函数,系统不会再提供其他构造函数;
  • 拷贝构造函数形如:test(const test &another){},使用const避免拷贝过程中修改类名;
  • 在对含有指针成员的对象进行拷贝时,必须要自定义拷贝构造函数,使拷贝后的指针成员有自己的内存空间,即进行(深拷贝),如果使用默认拷贝构造函数,则两个指针会指向同一个对象内存空间,析构时要析构两次,会发生内存溢出。
  • 类中的const常量必须在初始化列表中进行初始,不能使用赋值的方法进行初始化
  • frend友元函数(友元类),允许函数(友元类)使用类的私有成员。
  • 函数的重载就是简单的静态多态。
  • 一个基类中如果包含一个或者多个虚函数,就是抽象基类,抽象基类不能也没必要定义对象。
  • 抽象基类体现了本类族中的共性,把各类中 共有的成员函数集中在抽象基类中声明。
  • 操作符的重载有两种方式,即友元函数或者类成员函数。
  • C++中使用<fstream>头文件来操作文件。Fstream read("路径");先声明一个ifstream对象,不进行初始化,然后将对象和open()关联起来。
  • 命令行技术:int main(int argv,char*argv[]){}  ,其中int argc 是参数的个数,而char*argv[]是参数。
  • 头文件<cctype> 中的toupper实现小写转换为大写字母。
  • 库就是二进制文件。使用需要头文件和制作出来的库。
  • c语言中const修饰的是伪常量,编译器会给分配内存。c++中const定义的常量使用指针也不可修改;
  • 引用起别名:int &b = a;引用必须初始化,且不可修改;给数组其别名:int(&parr)[]=arr;
  • 引用的实质就是指针常量;
  • 函数重载的原理其实是编译器内部进行自动改名;
  • c语言中没有函数重载,如果C++想调用c语言的函数,01直接在cpp中需要使用extern+函数名;进行声明;02或者在c文件中使用#ifdef。。。。进行声明;
  • 构造函数与类名相同,没有返回值(注意是没有返回值,而不是void返回值)(可以有参数);
  • 调用默认无参构造函数不需要加()括号;
  • 对于浅拷贝来说,如果属性中有指向堆区的数据,只是简单的拷贝了数据的内存地址,但是释放的时候却释放两次,程序崩溃,解决的方法是进行深拷贝,手动定义拷贝构造函数,在拷贝构造函数中重新申请新的内存空间,再把元数据赋值到新空间中;
  • l_name = (char*)malloc(strlen(p.l_name) + 1);之所以加1是因为字符串最后还有(\0);strlen()计算的是字符串的有效长度;
  • 类初始化数据有两种方法:
  • (01)全局变量的检测;
  • (02)函数检测的增强;参数类型增强,返回值检测增强,函数调用的参数检测增强;
  • (03)类型转换增强;
  • (04)struct增强;c语言中struct成员中不可以有函数;c++中可以添加;c语言中实现结构体必须加struct关键字,c++中可以不加struct;
  • (05)c++中增加bool类型;
  • (06)三目运算符增强;c语言中返回的是值;c++中返回的值变量,可以直接重新赋值;
  • c++对c语言的增强:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值