C++面向对象基础

继承

c++中 类和类直接存在某种特殊的关系,定义这些类时,成员除了有自己的特性,还有上一级类的共性,这个时候可以利用继承,减少代码的重复

继承的好处:减少代码的重复

语法: class 子类 (派生类): 继承方式 父类(基类)

class Base()
{
  public :
   int m_A;
};
class  son : public Base
{
    public : 
int m_ b ;   //父类Base中的m_A通过继承的方式传递了下来
//类son中本质上有两个属性。 m_A被隐藏了
};

继承方式:公共继承(public) 、 保护继承(protected)、私有继承(private)

各继承方式的共同点:子类都不能访问父类中的私有成员

各继承方式的区别:public(公共继承)子类继承父类中的各个权限的属性;protected(保护继承)子类除父类中的私有权限之外, 父类中的其它权限在子类中全部变成protected保护权限;

private(私有继承)子类除父类中的私有权限之外,父类中的其它权限在子类中全部变成私有权限

如下图理解:

 注意: 父类中的所以成员都会被继承下来(包括私有成员只是不能访问),只是在子类中被隐藏了。

继承中对象模型:

通过VS的开发者人员命令窗口 可以访问对象的具体布局;如下图:

 

 同名成员函数和静态同名成员函数的处理

当子类和父类中出现同名的成员时,有两种方法可以区分:

(1)访问子类中的同名成员 -- 直接访问, 子类对象 . 同名成员

(2)访问父类中的同名成员 - - 需要加作用域: 当通过子类对象访问父类中同名成员时需要加上作用域 如: s. Base :: m_A;

注意:如果子类和父类有同名成员函数,子类中的同名成员函数会隐藏掉父类中的所有同名成员函数(包括同名成员函数的所有重载版本),此时想访问父类中的同名成员函数需要加上作用。

静态同名成员函数的处理与同名成员函数的处理相似

类中成员可以通过两种方式来访问,一种是通过对象访问, 一种是通过类名访问, 如果想用子类类名访问父类作用域下的成员时,需要加上 :: :: 如: Son :: Base :: m_A ;  第一个 ::表示通过类名访问,第二个 :: 表示访问父类作用域下的成员。

多继承: class 子类 : 继承方式 父类,继承方式 父类    

实际开放中不提倡使用多继承的方法。

多态

多态分为两类:静态多态和动态多态

静态多态:运算符重载、函数重载等,符用函数名,地址早绑定,在编译阶段就确定了地址

动态多态:派生类和虚函数实现运行时多态,地址晚绑定,在运行阶段才确定地址

virtual 是虚函数的关键字 , 令虚函数等于0 就变成了纯虚函数,用于纯虚函数的类也称为抽象类

抽象类的特点:不能实例化对象, 子类必须重写父类中的抽象类,不然也属于抽象类

多态产生的条件:

要有继承关系 ; 子类必须重写父类中的虚函数(重写:函数返回类型 函数名 参数列表 都相同)

 子类中的virtual可以不写。

多态实现的原理:

 解释:当类中有虚函数之后,会产生一个vfptr - 虚函数指针 ,此指针指向虚函数表 vftable 

虚函数表中的内容是 被virtual修饰的函数, 当子类继承父类之后,子类如果没有重写父类中的虚函数表的内容的话,子类中的虚函数表存放的是父类虚函数表中的函数,重写之后,子类中的虚函数表中的内容就替换成立重写之后的函数;当父类指针 或引用 执行子类对象时就发生多态 也就实现了传进哪个调用哪个。

虚析构和纯虚析构

当子类中有属性开辟在堆区时, 父类指针无法调用子类的析构函数,可能会出现内存泄漏问题

利用纯、虚析构来解决问题

虚析构和纯虚析构的共性

(1)可以通过父类指针来释放子类对象

(2)都需要有具体的实现

区别:

如果是纯虚析构,那么该类属于抽象类,无法实例化对象,纯虚析构需要具体的实现,也需要声明,在类内声明,类外具体实现 : 类名 :: ~类名 ()

文件操作

在c++中,程序运行时产生的数据都属于临时数据,运行结束就会被释放,通过文件可以使数据持久化。

C++中对文件的操作需要包含头文件 fstream

文件类型分为两种:

文本文件:文件以文本的ASCII码值形式存储在计算机中

二进制文件:文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们

文件操作的三大类:

ifstream(读文件)、 ofstream(写文件) 、 fstream(读写文件)

文本文件的写和读

(1)写

首先包含头文件 fstream ; 然后创建一个 流对象 : ofstream ofs;  再打开文件: ofs.open("文件的路径",打开方式) ; 写: ofs << "内容" << endl;  最后关闭文件: ofs.close();

文件的打开方式有: ois :: in (以读的形式打开)、 ios ::out(以写的形式打开) 、 ios :: binary (以二进制的方式打开)

打开方式 可以两个一起 用 | 隔开

#include<fstream>
ofstream ofs;
ofs.open("test.txt" ios :: out ); //如果不指定路径,默认放在源文件路径下
ofs << "hello world " << endl;
ofs.close();

(2)读

首先还是包含头文件fstream ; 创建流对象 ifstream  ifs; 打开文件这里要判断是否打开成功 用is_open函数; 然后再读文件; 最后关闭

读文件的方式有四种

#include<fstream>
ifstream ifs;
ifs.open("text.txt" ios :: in) ;
//判断文件是否打开成功
if(! ifs.is_open())  // 利用!取反符
{
     cout << "文件打开失败" << endl;
}
//读的第一种方式
char buf[1024] = { 0 };
while(ifs >> buf)
{
       cout << buf << endl;
}
//第二种
char buf[1024] = { 0 };
while(ifs.getline(buf,sizeof(buf)))
{
       cout << buf << endl;
}
//第三种
string buf;
while(getline(ifs,buf))
{
      cout << buf << endl;
}
//第四种
char c;
while((c = ifs.get()) !=EOF) //EOF end of file 文件结束标志
{
  cout << c << endl;
}

ifs.close();

读的方法个人喜欢第三种,其次使第二种, 第四种不推荐

二进制文件的读和写

具体步骤都差不多,在打开文件那一步 需要加上二进制打开方式 如:ios :: in | ios :: binary

第四步写文件 需要利用write函数 : ofs.write((const char * )&p ,sizeof(p)); 指针指向一个对象,sizeof计算写入此对象的大小,注意需要先创建一个对象在进行写入

读的步骤也差不多,但是在第四步 读的时候需要利用read函数 如:ifs.read((char *)&p,sizeof(p))

sizeof计算的是读的大小,也必须先有一个对象,对此对象进行读和写

#include<iostream>
#include<fstream>
int main()
{

   ofstream ofs;
   ofs.open ("person.txt",ios :: out | ios :: binary);
   //写的时候利用write函数
   //首先需要创建对象写内容
   Person p("zhangsan",20);
   
   ofs.write((const char *) &p,sizeof(p));  //利用write函数写入
  ofs.close
  

  ifstream ifs;
  ifs.open("person.txt",ios :: in | ios :: binary);
  Person p;
   ifs.read((char *) &p,sizeof(p)); //利用read函数读取对象种的内容
   cout << p << endl; //需要利用左移运算符重载
   ifs.close();
   return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值