C++学习笔记之高级语法
高级语法
面向对象——类
C++使用struct、class来定义一个类:
- struct 的默认成员权限是public;
- class 的默认成员权限是private;
- 除此之外,二者基本无差别。
struct 更适合看成是一个数据结构的实现体,class 更适合看成是一个对象的实现体。
对象的属性
C++没有类似于C#的属性,需要自己实现Get、Set方法,代码如下:
class Test { public: Test(){} Test(int _m):_cm(_m){} int GetCm() const { return _cm; } void SetCm(int c) { _cm=c; } private: int _cm; };
注:Get函数需要用const修饰为常函数,参考C++ 类class const修饰成员函数。
运算符重载
运算符重载函数既可以声明为类的成员函数,也可以声明为所有类之外的全局函数,参考 C++学习27 用全局函数重载运算符 :
- 将运算符重载函数声明为类的成员函数时,二元运算符的参数只有一个,一元运算符不需要参数。之所以少一个参数,是因为这个参数是隐含的。
- 将运算符重载函数声明为全局函数时,二元操作符就需要两个参数,一元操作符需要一个参数,而且其中必须有一个参数是对象,好让编译器区分这是程序员自定义的运算符,防止程序员修改用于内置类型的运算符的性质。
复合赋值操作符是指 += , *= , -= 这一类由基本算数运算符( + 、 - 、 * 、 / )或位运算符(| 、 & 、~等)加 = 号构成的运算符。它们把左右操作数进行相应运算后的结果赋值给左操作符, 复合赋值操作符的返回值,默认是左值。比如a += b;中的a。
在进行复合赋值操作符重载定义的时候,需要注意,其返回值,应该为( * this)<类成员>或者第一个也就是左操作数<非成员函数>,参考 C++运算符重载 :
//类成员函数方法实现运算符重载 className & className::operator +=(className & right) { return (*this) = (*this) + right; } //全局函数方法实现运算符重载 className& operator +=(className& left, className& right) { return left = left + right; }
常用的运算符重载(类成员函数)定义如下:
// 运算符重载 className operator+(const className &c) const; className& operator+=(const className &c); className operator-(const className &c) const; className& operator-=(const className &c); className operator*(const className &c) const; className& operator*=(const className &c); className operator/(const className &c) const; className& operator/=(const className &c); bool operator==(const className &c) const; 2419 bool operator!=(const className &c) const; bool operator>(const className &c) const; bool operator>=(const className &c) const; bool operator<(const className &c) const; bool operator<=(const className &c) const; // 前置和后置++ className& operator++(); //前置++ className operator++(int); //后置++ className& operator--(); //前置-- className operator--(int); //后置-- //IO重载,全局函数 friend ostream& operator<<(ostream& os, const className &x); friend istream& operator>>(istream& is, className &x);
拷贝构造函数
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象,参考 C++ 拷贝构造函数 。
拷贝构造函数通常用于:
- 通过使用另一个同类型的对象来初始化新创建的对象。
- 复制对象把它作为参数传递给函数。
- 复制对象,并从函数返回这个对象。
拷贝构造函数的最常见形式如下:
classname (const classname &obj) { // 构造函数的主体 }
IO缓存
cin.ignore(numeric_limits<std::streamsize>::max(), '\n'); // 清空缓存区脏数据
头文件的重复包含问题
方案1:使用宏来防止同一个文件被多次包含:
#ifndef _SOMEFILE_H #define _SOMEFILE_H //头文件内容 #endif
优点:可移植性好;
缺点:无法防止宏名重复,难以排错;
方案2:使用编译器来防止同一个文件被多次包含:
#pragma once //头文件内容
优点:可以防止宏名重复,易排错;
缺点:可移植性不好;
总结:只考虑Windows系统可以用方案2,否则用方案1。
深拷贝与浅拷贝
浅拷贝:只拷贝指针地址,C++默认拷贝构造函数与赋值运算符重载都是浅拷贝;节省空间,但容易引发多次释。
深拷贝:重新分配堆内存,拷贝指针指向内容;浪费空间,但不会导致多次释放。
兼有二者的优点:
- 方案一:引用计数;
- 方案二:C++新标准的移动语义:
// 移动赋值运算符 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&& other) { if (other.m_data != NULL) { // 资源让渡 m_data = other.m_data; other.m_data = NULL; } } //使用 String s1("Hello"); String s2A(std::move(s1)); // 移动构造函数 String s3A; // 无参构造函数 s3A = std::move(s2A); // 移动赋值运算符
面向对象三大特性
封装性:数据和代码捆绑在一起,避免外界干扰和不确定性访问,封装可以使得代码模块化;
继承性:让某种类型对象获得另一个类型对象的属性和方法,继承可以扩展已存在的代码;
多态性:同一事物表现出不同事物的能力,即向不同对象会产生不同的行为,多态的目的则是为了接口重用;
- C++ 学习笔记 <1> C++ 语法基础知识
- android_c++ 高级编程NDK学习笔记四
- JavaScript高级程序设计(第3版)学习笔记2 js基础语法
- c++ 高级编程学习笔记_1
- C++学习笔记之语法2
- C++语法学习笔记
- c++ 学习笔记(高级linux编程) day6
- c++学习笔记(部分语法及c++11新特性)
- Python高级语法——正则表达式和XPath——学习心得笔记
- Python高级语法——多线程——学习心得笔记
- android_c++ 高级编程NDK学习笔记五
- 【学习笔记】C++高级程序设计:STL:Map 和 Multimap
- c++ 学习笔记(高级linux编程) day1
- c++学习笔记-------《c++自学通》第十二章 高级引用和指针
- C++学习笔记:异常的基本语法
- C++面向对象高级编程(上)学习笔记
- C++学习笔记————VS2017下出现 error C2760: 语法错误: 意外的令牌“标识符”,预期的令牌为“;” 的解决办法
- [编译原理学习笔记2-1] 高级语言及其语法描述
- 学习笔记----Python高级语法
- Pro visual c++/cli and .net 2.0 platform2 学习笔记(10 第四章 高级C++/CLI)