基础123

多态

动态多态满足条件 (函数地址晚绑定
1.有继承关系;
2.子类重写父类的虚函数;//函数返回值类型,函数名,参数列表完全相同
使用条件:
******父类的指针或引用 指向子类对象*********
例:animal&a=cat;
       a.speak(); 

void dowork(f* a)

void show(animal& a)//父类引用
{
    a.laugh();//父类虚函数
}

非静态成员函数不占类内存

当子类重写父类的虚函数,子类的虚函数表 内部 会替换成 子类的虚函数地址;

virtual加父类内函数,即创建了一个虚函数指针,在虚函数表内记录虚函数的地址

纯虚函数:virtual 返回值类型 函数名(参数列表)=0;//当类中有了纯虚函数,这个类成为抽象类
抽象类特点
1.无法实例化对象;即不能创建对象
2.子类必须重写抽象类的纯虚函数,否则也属于抽象类

 虚析构与纯虚析构(可以父类指针释放子类对象,都需要有具体的函数实现)
如果是纯虚析构,此类属于抽象类,无法实例化对象
虚析构语法:virtual ~类名(){}
纯虚析构语法:virtual ~类名()=0;类外实现:类名::~类名(){};//必须类外有实现

继承 

继承:减少重复代码;
语法:
class 子类:继承方式 父类{};//子类也叫派生类,父类也叫基类;子类含父类所有内容

//类外访问不到保护权限 

父类中私有权限的内容子类无法继承;
public,公有继承,内容按原访问权限;
protected,保护继承,内容变为保护权限;
private,私有继承,内容变为私有权限

父类中所有非静态成员属性都会被子类继承;
父类中的私有成员被编译器隐藏,不能访问,但被继承了

继承中先构造父类,再构造子类,析构顺序相反;类似栈(先进后出

如果子类与父类变量重名;要给父类中的变量加作用域,
即:子类.父类名::变量名
直接调用,调用的均为子类成员 ;
如果子类冲出现和父类同名的成员函数,子类的同名成员会隐藏掉父类的所有同名成员函数(包括重载)
静态函数,变量同理;
(静态成员,类内声明,类外初始化)

子类可以继承多个父类;当有同名成员时,加作用域;(慎用
例: class son:public f1,protected f2........{}

继承之前,加关键字 virtual 变为虚继承;原基类成为虚基类,数据只有一份,防止菱形继承(子类继承两份相同的数据
例:class sheep:virtual public animal{};

 模板

template<typename T>//声明一个模板,T是一个通用数据类型
typename可以替换为class
后面紧跟函数例:void swap(T &a,T &b)
自动类型推导:调用函数时可以直接调用;
注意事项:1.必须推导出一致的数据类型T
2.模板必须要确定T的数据类型才可使用,若函数内未使用T,则例: func<int>();
或:函数名<数据类型>(变量);swap<int>(a,b)

调用规则
1、若普通函数和函数模板都可以调用,优先调用 普通函数
2、可以通过 空模板 参数列表 强制调用 函数模板
即<>
3、函数模板可以重载
4、如果函数模板可以产生更好的匹配,优先调用函数模板 
即普通函数有隐式类型转换 
利用具体化类名,实现优先调用;例
template<>bool mycompare(person&p1,person&p2)

类模板没有自动类型推导,必须加<>
类模板在模板参数列表中可以有默认参数,
例:template<class age=int>

类模板中的成员函数不是一开始就创建的,在调用时才创建

通过类模板创建的对象向函数传参时,指定转入类型;
例:void func(person<string,int>&p)或创建模板用T
例:template<class T1,class T2>
      void func(person<T1,T2>&P>

       template<class T>
       void func(T&p)

模板继承时,要指定父类中的数据类型
例:class son::public base<int>
若要灵活指定父类中的T类型,子类也需要模板
例:template<class T>
      class son::public base<T>

类模板成员函数类外实现
构造函数;
template<class T1,class T2>
person<T1,T2>::person(T1 name,T2 name)
普通函数:
template<class T1,class T2>
void person<T1,T2>::function();

模板分文件编写方式
1.直接包含源文件
2.将.h和.cpp文件写在一起,后缀改为hpp,写在头文件中

在类模板内使用friend,即变为全局函数
例 friend void func(person<T1,T2>p)
类内实现直接写;
类外实现需加空模板参数列表,且需要让编译器提前知道这个函数的存在,即在声明前实现,(记得声明类模板)
例: friend void func<>(person<T1,T2>p);

typeid(对象).name;可以查看对象的类型

文件操作

文本文件:
头文件:#include<fstream>
操作文件三大类://
1.ofstream:写操作;
2.ifstream:读操作;
3.fstream:读写操作;//最好用;
先创建个对象
fstream ofs;//在创建对象时就可以打开文件,例:fstream ofs("路径",打开方式);
打开文件:
ofs.open("文件路径",打开方式);
打开方式:
ios::in;为读文件打开文件;
ios::out;为写文件打开文件;
ios::ate;初始位置在文件尾;
ios::app;追加方式写文件;
ios::trunc;如果文件存在先删除再创建;(ofstream
ios::binary;二进制方式;
文件打开方式可配合使用,通过“|”;例:ios::binary | ios::out
写数据:
ofs<<"写入的数据";
关闭文件:
ofs.close();

使用 is_open();判断是否成功打开
通过>>读取数据;
或者使用ofstream类内函数: getline(读到哪的指针,大小)
或使用全局函数:getline(创建的类对象,字符串)例:
string buf;
while ( 
b.close();
EOF:end of file;文件结尾

二进制写文件:例
person p = { 18,"张三" };
ofs.write((const char*)&p, sizeof(person));*****

二进制读文件,例:
person p;
ifs.read((char*)&p, sizeof(person));
cout << p.m_age << p.m_name << endl;//读到类对象中;

运算符重载


运算符重载也可以发生函数重载

+:类名 operator+(类1,类2)//最好用引用
使用例:person p3=p1+p2;//本质:operator+(p1,p2);
类内成员函数同理

左移<<:必须用全局函数,并用引用的方式&
例://cout数据类型:ostream,
ostream& operator<<(ostream&cout,person&p)
{
  cout<<p....<<.....
  return cout;//返回cout,方便连续使用
}

自增自减:
int代表占位参数,可以用于区分前置和后置递增//利用函数重载
前置递增返回引用
后置递增返回值
例:类名& operator++()
{....
  return 类名
}

赋值=:编译器提供的为浅拷贝,易造成堆区内存重复释放
例:person& operator=(person& p)
{
    if (m_age != NULL)//先判断原先变量是否为空
    {
        delete m_age;
        m_age = NULL;
    }
    m_age = new int(*p.m_age);//开辟新的堆区内存
    return *this;//返回本身,方便连等操作
}

匿名函数对象:
类名();当前行被执行完毕直接释放;

函数调用重载
例:void operator()(string text)
{
    cout << text << endl;
}
调用只需创建一个对象,a(“内容”)//因与函数调用像,成为仿函数

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值