C++高级语法

news/2024/4/18 18:50:40

文章目录

  • C++高级语法
    • 面向对象 -- 类/结构体
      • 抽象-具体类型
    • 标准I/O流
      • I/O流
      • I/O缓存区
    • 文件操作
    • 头文件的重复包含问题
    • 深拷贝和浅拷贝,写时复制
    • 面向对象的三大特性
      • 面向对象是什么

C++高级语法

面向对象 – 类/结构体

  • C++使用class定义一个类,使用struct定义一个结构体

struct的默认成员权限是public,class的默认成员权限是private,除此之外二者基本没有差别。

抽象-具体类型

  • 让自定义类型的类像内置类型一样

封装和函数重载示例:

Complex.h

#include <iostream>
using namespace std;class Complex
{
public:Complex();                                    // 默认构造函数Complex(double r,  double i);      // 构造函数virtual ~Complex();                      // 析构函数Complex(const Complex& x);      // 拷贝构造Complex& operator=(const Complex &c); // =号运算符double GetReal( ) const { return _real; }void SetReal(double d) { _real = d; }double GetImage() const { return _image; }void SetImage(double i) { _image = i; }// 运算符重载Complex operator+(const Complex &c) const;Complex& operator+=(const Complex &c);Complex operator-(const Complex &c) const;Complex& operator-=(const Complex &c);Complex operator*(const Complex &c) const;Complex& operator*=(const Complex &c);Complex operator/(const Complex &c) const;Complex& operator/=(const Complex &c);bool operator==(const Complex &c) const;bool operator!=(const Complex &c) const;bool operator>(const Complex &c)  const;bool operator>=(const Complex &c) const;bool operator<(const Complex &c) const;bool operator<=(const Complex &c) const;// 前置和后置++Complex& operator++();   //前置++Complex operator++(int); //后置++Complex& operator--();   //前置--Complex operator--(int); //后置--//protected:friend ostream& operator<<(ostream& os, const Complex &x);friend istream& operator>>(istream& is, Complex &x);private:double _real;             // 复数的实部double _image;         // 复数的虚部
};

Complex.cpp

#include "Complex.h"Complex::Complex()
{_real = 0.0;_image = 0.0;//cout << "Complex::Complex()" << endl;
}Complex::Complex(double r, double i)
{_real = r;_image = i;//cout << "Complex::Complex(double r, double i)" << endl;
}Complex::Complex(const Complex& c)
{_real = c._real;_image = c._image;//cout << "Complex::Complex(const Complex& c)" << endl;
}Complex& Complex::operator= (const Complex& c)
{if (this != &c){_real = c._real;_image = c._image;}return *this;
}Complex::~Complex()
{_real = _image = 0.0;//cout << "Complex::~Complex()" << endl;
}Complex Complex::operator+ (const Complex& c) const
{//Complex tmp;//tmp._real = _real + x._real;//tmp._image = _image + x._image;//return tmp;return Complex(_real + c._real, _image + c._image);
}Complex& Complex::operator+= (const Complex& c)
{_real += c._real;_image += c._image;return *this;
}Complex Complex::operator-(const Complex &c) const
{return Complex(_real - c._real, _image - c._image);
}Complex& Complex::operator-=(const Complex &c)
{_real -= c._real;_image -= c._image;return *this;
}Complex Complex::operator*(const Complex &c) const
{return Complex(_real*c._real - _image*c._image, _real*c._image + _image*c._real);
}Complex& Complex::operator*=(const Complex &c)
{Complex tmp(*this);  //拷贝构造函数_real = tmp._real*c._real - _image*c._image;_image = tmp._real*c._image + tmp._image*c._real;return *this;
}Complex Complex::operator/(const Complex &c) const
{double t = c._real*c._real + c._image*c._image;return Complex((_real*c._real - _image*(-c._image)) / t, (_real*(-c._image) + _image*c._real) / t);
}Complex& Complex::operator/=(const Complex &c)
{Complex tmp(*this);  //拷贝构造函数double t = c._real*c._real + c._image*c._image;_real = (tmp._real*c._real - tmp._image*(-c._image)) / t;_image = (tmp._real*(-c._image) + tmp._image*c._real) / t;return *this;
}bool Complex::operator==(const Complex& c) const
{return (_real == c._real) && (_image == c._image);
}bool Complex::operator!=(const Complex& c) const
{return !( (_real == c._real) && (_image == c._image) );
}bool Complex::operator>(const Complex &c)  const
{return (_real > c._real) && (_image > c._image);
}bool Complex::operator>=(const Complex &c) const
{return (_real >= c._real) && (_image >= c._image);
}bool Complex::operator<(const Complex &c) const
{return (_real < c._real) && (_image < c._image);
}bool Complex::operator<=(const Complex &c) const
{return (_real <= c._real) && (_image <= c._image);
}Complex& Complex::operator++ () // 前置++
{_real++;_image++;return *this;
}Complex Complex::operator++ (int) // 后置++
{//Complex tmp(*this);//_real++;//_image++;//return tmp;return Complex(_real++, _image++);
}Complex& Complex::operator--()   //前置--
{_real--;_image--;return *this;
}Complex Complex::operator--(int) //后置--
{return Complex(_real--, _image--);
}ostream& operator<<(ostream& os, const Complex &x)
{os << "real value is  " << x._real << "  image value is " << x._image;return os;
}istream& operator >> (istream& is, Complex &x)
{is >> x._real >> x._image;return is;
}

标准I/O流

I/O流

  • 传统C中的I/O流有printf,scanf,getch,gets等函数:他们的问题是:

    1. 不可编程,仅仅能识别固有数据类型
      1. 代码可移植性差,有很多坑
  • C++中的I/O流istream,ostream等:

    1. 可编程,对于使用类库的设计者来说很有用
    2. 简化编程,使得I/O风格一致

I/O缓存区

  • 标准IO提供三种类型的缓存模式
    • 按块缓存:如文件系统
    • 按行缓存:\n
    • 不缓存。

文件操作

  • 输入流的七点和输出流的终点都可以是磁盘文件
  • 文件:C++把每个文件都看成是一个有序的字节序列,每个文件都是以文件结束标志结束
  • 按照文件中的数据的组织形式可以把文件分成:
    • 文本文件:文件中信息形式为ASCII码文件,每个字符占一个字节
    • 二进制文件:文件中信息的形式与其在内存中的形式相同

文件操作步骤:

  1. 打开文件用于读和写 open;
  2. 检查是否打开成功 fail;
  3. 读或者写操作;
  4. 检查是否读完EOF;
  5. 使用完成之后关闭文件;

文件的打开方式:

方式描述
ios::in打开文件进行读操作
ios::out打开文件进行写操作
ios::ate打开一个已有输入或者输出文件并查找文件结尾
ios::app打开文件以便在文件尾部添加数据
ios::nocreate如果文件不存在则打开失败
ios::trunc如果文件存在,清除文件内容
ios::binary以二进制形式打开
#include <string>
#include <fstream>
#include <iostream>
using namespace std;static const int bufferLen = 2048;
bool CopyFile(const string& src, const string& dst)
{// 打开源文件和目标文件// 源文件以二进制读的方式打开// 目标文件以二进制写的方式打开ifstream in(src.c_str(), ios::in | ios::binary);ofstream out(dst.c_str(), ios::out | ios::binary | ios::trunc);// 判断文件打开是否成功,失败返回falseif (!in || !out){return false;}// 从源文件中读取数据,写到目标文件中// 通过读取源文件的EOF来判断读写是否结束char temp[bufferLen];while (!in.eof()){in.read(temp, bufferLen);streamsize count = in.gcount();out.write(temp, count);}// 关闭源文件和目标文件in.close();out.close();return true;
}int main()
{cout << CopyFile("Blue Daube.mp3", "Blue Daube2.mp3") << endl;//int a;//int index = 0;//fstream fout;//fout.open("testBuffer.txt", ios::app);if (fout.fail())//if (!fout)//{//	cout << "open file failed" << endl;//}//while (cin >> a)//{//	//cout << "The numbers are: " << a << endl;//	fout << "The numbers are: " << a << endl;//	index++;//	if (index == 5)//	{//		break;//	}//}//cin.ignore(numeric_limits<std::streamsize>::max(), '\n');  // 清空缓存区脏数据//char ch;//cin >> ch;cout << "the last char is: " << ch << endl;//fout << "the last char is: " << ch << endl;//fout.close();return 0;
}

头文件的重复包含问题

  • 为了避免同一个文件被多次include ,有两种方式

    • #ifndef aa
      #define aa
      #endif
      

      使用宏来方式同一个文件被多次包含

      优点:可移植性好

      缺点:无法防止宏名称重复,难以排查错误

    • #program once

      使用编译器来防止同一个文件被多次包含

      优点:可以防止宏名重复,易排错

      缺点:可移植性不好

深拷贝和浅拷贝,写时复制

  • 浅拷贝:只拷贝指针地址,C++默认拷贝构造函数与赋值运算符都是浅拷贝,节省空间,但是容易引发多次释放;
  • 深拷贝:重新分配堆内存,拷贝指针指向内容。浪费空间,但不会导致多次释放;

如何同时具备二者的优点?

  • 使用引用计数
  • C++新标准的移动语义

String.h

#pragma once
class String
{
public:String(const char *str = NULL);                              // 普通构造函数String(const String &other);                                  // 拷贝构造函数String(String&& other);                                         // 移动构造函数~String(void);                                                         // 析构函数String& operator= (const String& other);             // 赋值函数String& operator=(String&& rhs)noexcept;		   // 移动赋值运算符friend ostream& operator<<(ostream& os, const String &c); // cout输出private:char *m_data; // 用于保存字符串
};

String.cpp

#include "stdafx.h"// _CRT_SECURE_NO_WARNINGS// String 的普通构造函数
String::String(const char *str)
{if (str == NULL){m_data = new char[1];if (m_data != NULL){*m_data = '\0';}else{exit(-1);}}else{int len = strlen(str);m_data = new char[len + 1];if (m_data != NULL){strcpy(m_data, str);}else{exit(-1);}}
}// 拷贝构造函数
String::String(const String &other)
{int len = strlen(other.m_data);m_data = new char[len + 1];if (m_data != NULL){strcpy(m_data, other.m_data);}else{exit(-1);}
}// 移动构造函数
String::String(String&& other)
{if (other.m_data != NULL){// 资源让渡m_data = other.m_data;other.m_data = NULL;}
}// 赋值函数
String& String::operator= (const String &other)
{if (this == &other){return *this;}// 释放原有的内容delete[ ] m_data;// 重新分配资源并赋值int len = strlen(other.m_data);m_data = new char[len + 1];if (m_data != NULL){strcpy(m_data, other.m_data);}else{exit(-1);}return *this;
}// 移动赋值运算符
String& String::operator=(String&& rhs)noexcept
{if(this != &rhs){delete[] m_data;m_data = rhs.m_data;rhs.m_data = NULL;}return *this;
}// String 的析构函数
String::~String(void)
{if (m_data != NULL){delete[] m_data;}
}ostream& operator<<(ostream& os, const String &c)
{os << c.m_data;return os;
}

main.cpp

int main()
{String s1("Hello");                          // 构造函数cout << s1 << endl;//String s2 = s1;                             // 调用拷贝构造函数String s2(s1);                                  // 调用拷贝构造函数cout << s2 << endl;String s2A(std::move(s1));              // 移动构造函数cout << s2A << endl;String s3;                                        // 无参构造函数cout << s3 << endl;s3 = s2;                                           // 调用赋值函数cout << s3 << endl;String s3A;                                      // 无参构造函数s3A = std::move(s2A);                    // 移动赋值运算符cout << s3A << endl;return 0;
}

面向对象的三大特性

  • 封装性:数据和代码捆绑在一起,避免外界干扰和不确定性访问,封装可以使得代码模块化
  • 继承性:让某种类型对象获得另一个类型对象的属性和方法,继承可以扩展已存在的代码
  • 多态性:同一事物表现出不同事物的能力,即面向不同的对象产生不同的行为,多态的目的是为了接口重用

面向对象是什么

  • 面向对象是软件工程发展到一定的阶段为了管理代码和数据提出的一种方法,它没有解决以前解决不了的问题,不是万能的
  • 面向对象不是对现实世界的映射,但他的封装性可以把问题简化,便于抽象;它的多台可以减少代码重复,避免重新发明轮子;它的多台可以实现灵活的功能扩展,提升开发效率
  • 面向对象为我们便捷开发出能适应软件变化的软件提供了可能

http://www.ppmy.cn/news/101273.html

相关文章

studio one6免费版下载及配置要求 附精调效果包

提到编曲软件&#xff0c;就不得不说这款水果编曲软件。它对新手和老手都比较友好&#xff0c;是一款较为经典的编曲软件。 这款软件提供了强大而全面的音符、音效编辑器&#xff0c;可以在其中插入各种乐器声音&#xff0c;如果内置乐器无法满足编曲需求&#xff0c;还可以外…

Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程

1、客户端API操作 1.1 IDEA 环境搭建 前提&#xff1a;保证 hadoop102、hadoop103、hadoop104 服务器上 Zookeeper 集群服务端启动。 1、创建一个工程&#xff1a;Zookeeper 2、添加pom文件 <?xml version"1.0" encoding"UTF-8"?> <project …

vue插槽使用总结

什么是插槽解决什么问题插槽的分类默认插槽具名插槽作用域插槽 什么是插槽 插槽就是子组件中的提供给父组件使用的一个占位符&#xff0c;用 表示&#xff0c;父组件可以在这个占位符中填充任何模板代码&#xff0c;如 HTML、组件等&#xff0c;填充的内容会替换子组件的标签。…

【Netty】一行简单的writeAndFlush都做了哪些事(十八)

文章目录 前言一、源码分析1.1 ctx.writeAndFlush 的逻辑1.2 writeAndFlush 源码1.3 ChannelOutBoundBuff 类1.4 addMessage 方法1.5 addFlush 方法1.6 AbstractNioByteChannel 类 总结 前言 回顾Netty系列文章&#xff1a; Netty 概述&#xff08;一&#xff09;Netty 架构设…

Linux——http协议1

目录 URL http协议 http请求 http响应 细节优化 makefile HttpServer.hpp HttpServer.cc Util.hpp

Hack The Box - 关卡Dancing

SMB(全称是Server Message Block)是一个协议名&#xff0c;可用于在计算机间共享文件、打印机、串口等&#xff0c;电脑上的网上邻居就是靠它实现的。 SMB 是一种客户机/服务器、请求/响应协议。通过 SMB 协议&#xff0c;客户端应用程序可以在各种网络环境下读、写服务器上的…

软考A计划-试题模拟含答案解析-卷八

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

若依源码解析:代码生成ruoyi-generator

文章目录 摘要代码生成器的使用数据库连接配置数据库表设计代码生成器配置修改mybatis别名配置&#xff0c;增加对com.cyl包名的识别修改mybatis的mapper扫描包路径 代码生成代码输出模板配置 代码生成器原理模板引擎&#xff1a;Velocity使用Velocity模板引擎的一般流程模板语…

Java设计模式-解释器模式

简介 设计模式是软件开发中重要的概念之一&#xff0c;它们为我们提供了可重用、灵活和可扩展的解决方案。在Java领域中&#xff0c;解释器模式是一种强大的设计模式&#xff0c;它能够将复杂的问题拆分成简单的表达式&#xff0c;并提供一种灵活的方式来解释和执行这些表达式…

律师使用ChatGPT 进行法律文献检索提交了错误信息;李开复表示,威力强大的大模型将彻底变革人工智能

&#x1f680; 一名律师使用ChatGPT 进行法律文献检索提交了错误信息 近日&#xff0c;一名律师在法庭案件中使用聊天机器人 ChatGPT 进行法律文献检索&#xff0c;结果提交了错误信息&#xff0c; 揭示了人工智能在法律领域的潜在风险&#xff0c;包括误传错误信息。 该事件…

数字化时代,企业面临哪些共同的挑战?

在这种全新的社会、商业环境下&#xff0c;各行各业的企业都开始寻求探索新的商业模式&#xff0c;通过转型适应当前时代的转变&#xff0c;促进业务健康持续的发展。所以数字化成为了企业进行转型的工具&#xff0c;也成为了众多领域内企业对未来的共识。 一、管理挑战 ●经…

Logisim 头歌 偶校验编码设计图解及代码(计算机组成原理)

努力是为了不平庸~ 学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。 急的同学请直接点击目录跳到下方解答处&#xff01;&#xff01; 目录 图解&#xff1a; 代码题解&#xff08;免费&#xff09;&#xff1a; 实…

做外贸算运费的时候需不需要多算一些

看到一个网友在一篇文章下留言说&#xff1a;客户算运费的时候需不需要多算一些 听公司老员工说给客户算运费要多加20% 这样合适吗 我个人感觉有点离谱。 那我们就这个话题&#xff0c;谈一谈运费是否要多加一些呢&#xff1f;为什么要多加一些&#xff1f; 首先&#xff0c;要…

swagger页面 doc.html出不来,swagger-ui/index.html能出来

swagger页面 doc.html出不来&#xff0c;swagger-ui/index.html能出来。前前后后折腾了很久&#xff0c;jar包冲突&#xff0c;jar包版本&#xff0c;添加路径啥的都弄了&#xff0c;就是出不来。 后来全局搜索“doc.html”页面发现能出来的项目能搜到这个页面&#xff1a; 定…

springboot+vue+java旅行旅游景点酒店预订出行订票系统eaog5

线上旅行信息管理系统要求实现以下功能&#xff1a; a.景点管理&#xff0c;展示景点的基础信息&#xff0c;介绍等信息。 b.酒店管理,展示酒店的基础信息&#xff0c;介绍等信息。 c.评价管理&#xff0c;可以查看景点或酒店的相关评价信息&#xff0c;客户消费完&#xff0c;…

实时频谱-3.1实时频谱分析仪测量

RSA 测量类型 泰克RSA 可以在频域、时域、调制域和统计域中工作。 频域测量 基本频域测量是实时 RF 数字荧光显示(DPX)频谱显示测量、频谱显示测量和频谱图显示测量功能。 DPX 频谱 DPX 频谱测量对 RSA 发现其它分析仪漏掉的难检信号的能力至关重要。在所有泰克 RSA 中&am…

《面向对象程序设计》实践任务书

《面向对象程序设计》实践任务书 一、基本要求 &#xff08;1&#xff09;要求利用面向对象的方法以及c编程语言来完成系统的设计&#xff1b; &#xff08;2&#xff09;要求在设计的过程中&#xff0c;建立清晰的类层次&#xff1b; &#xff08;3&#xff09;自行设计文件保…

electron-vue 运行报错 Object.fromEntries is not a function

文章目录 1. 背景2. 解决方案2.1 第一步&#xff1a;安装依赖2.2 第二步&#xff1a;项目中引入 3. 组件详解 1. 背景 最近研究一款桌面端应用的开发框架electron-vue&#xff0c;在按照 electron-vue官方文档 操作之后操作如下&#xff0c;Object.fromEntries is not a funct…

C语言编程 7-12 日期格式化

世界上不同国家有不同的写日期的习惯。比如美国人习惯写成“月-日-年”&#xff0c;而中国人习惯写成“年-月-日”。下面请你写个程序&#xff0c;自动把读入的美国格式的日期改写成中国习惯的日期。 输入格式&#xff1a; 输入在一行中按照“mm-dd-yyyy”的格式给出月、日、年…

从0到整写一个Mini-Spring/Web框架实现基础的功能

文章持续更新中… 1. 针对于Spring/Web的执行流程 配置阶段 1.1 配置Web.xml —> 我们自己写的DispatcherServlet 1.2 设定init-param —> contextConfigLocation classpath:application.properties 1.3 设定url-pattern —> /* 1.4 配置Annotation —> XXCOntro…