C++面向对象程序设计 (学习笔记)

C++面向对象程序设计 学习笔记

1.引用

  • 1.引用不是定义一个新的变量,而是给已存在的变量取一个别名,编译器不会为引用变量开辟内存空间,他和引用的变量共用一块内存空间。

示例如下:

#include<iostream>
using namespace std;
int main(){
	int x = 5;
	int &y = x;
	y = 20;
	cout<<"x = "<<x<<endl;
	cout<<"y = "<<y<<endl;
	int &z = y;
	z = 30;
	cout<<"x = "<<x<<endl;
	cout<<"y = "<<y<<endl;
	cout<<"z = "<<z<<endl;
}

上述代码中,x分别被y和z引用,所以改变x,y,z 任意一个的值
那么x,y,z 三个的值都会被改变(相当于一个人有三个称呼,不管叫那个,她都会回应你)
在这里插入图片描述

  • 2.引用的性质
    1.引用在定义时必须初始化
    2.一个变量可以有多个引用
    3.引用一旦引用一个变量就不能引用其他变量了
    4.引用只能引用变量,不能引用常量和表达式

2.指针

1.指针的作用:可以通过指针间接访问内存
  • 内存编号是从0开始记录的,一般用十六进制数字表示
  • 可以利用指针变量保存地址
2.指针的定义与使用

示例如下:

#include<iostream>
using namespace std;
int main() {
	//定义指针
	int a = 10;
	//指针定义的语法:数据类型 * 指针变量名;
	int* p;
	//让指针记录变量a的地址
	p = &a;//在a前面加&是取址符号

	cout << "a的地址为: " << &a << endl;
	cout << "指针p为: " << p << endl;

	//使用指针
	//可以通过解引用的方式来找到指针间的内存 
	//即在指针p前加一个* 代表解引用找到指针指向的内存中的数据

	*p = 1000;
	cout << "a = " << a << endl;
	cout << "*p = " << *p << endl;

	system("pause");
	return 0;
}

在这里插入图片描述
上面便是代码运行的结果

3.指针所占内存空间

示例如下:

#include<iostream>
using namespace std;
int main() {
	//指针所占内存空间	
	int a = 10;
	int* p = &a;

	//32位操作系统占4个字节,64为操作系统占8位字节(任意数据类型)
	cout << "sizeof(int *) = " << sizeof(p) << endl;
	cout << "sizeof(float *) = " << sizeof(float *) << endl;
	cout << "sizeof(double *) = " << sizeof(double*) << endl;
	cout << "sizeof(char *) = " << sizeof(char*) << endl;

	system("pause");
	return 0;
}

在这里插入图片描述

4.空指针和野指针

空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针的内存是不可以访问的

空指针 示例如下:

#include<iostream>
using namespace std;
int main() {
	//空指针
	//1.空指针用于给指针变量进行初始化
	int* p = NULL;

	//2.空指针不可以进行访问
	//0~255之间的内存编号是系统占用的,因此不可以访问
	*p = 100;//写这个会报错
	cout<<*p<<endl;

	system("pause");
	return 0;
}

野指针 示例如下:
野指针:指针变量指向非法的内存空间

#include<iostream>
using namespace std;
int main() {
	//野指针
	//指针变量p指向地址编号为0x1100的空间
	int* p = (int *)0x1100;

	//访问野指针报错
	cout<<*p<<endl;

	system("pause");
	return 0;
}

总结:空指针和野指针都不是我们申请的空间,因此不要访问。

2.指针和数组 指针与函数的结合使用
  • 指针和数组
    作用:利用指针访问数组元素
#include<iostream>
using namespace std;
int main(){
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int *p = arr;//指向数组的指针 此时指向数组的首地址(数组名及数组的首地址)
	for(int i = 0;i < 10;i++){
		cout<<*p<<endl;
		p++;//p是指向地址的指针 *p是p地址的值
	}
	
	return 0;
}
  • 指针和函数
    作用:利用指针作为函数参数,可以修改实参的值
#include<iostream>
using namespace std;

void swap01(int a ,int b) {
	int temp = a;
	a = b;
	b = temp;
	cout << "swap01 a = " << a << endl;
	cout << "swap01 b = " << b << endl;
}
void swap02(int *p1, int *p2) {
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
	cout << "swap02 a = " << *p1 << endl;
	cout << "swap02 b = " << *p2 << endl;
}
int main() {
	//1.值传递
	int a = 10;
	int b = 20;

	swap01(a, b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	//地址传递

	swap02(&a, &b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	system("pause");

	return 0;
}

在这里插入图片描述

3.const,static,this关键字

  • 1.关键字const用来定义只读变量,被const定义的变量它的值是不允许改变的,即不允许给它重新赋值,即使是赋相同的值也不可以。所以说它定义的是只读变量,这也就意味着必须在定义的时候就给它赋初值。

4.运算符重载

c++预定义的运算符,只能用于基本数据类型的运算:整型 实型 字符型 逻辑型…
但不能在对象间进行计算,于是就有了运算符重载这个概念
运算符重载的形式

  • 运算符重载的实质是函数重载
  • 可以重载为普通函数,也可以重载为成员函数
  • 把含运算符的表达式转换成对运算符函数的调用
  • 把运算符的操作数转换成运算符函数的参数
  • 运算符被多次重载时,根据实参的类型决定调用那个运算符函数

运算符重载的形式

返回值类型 operator 运算符(形参表)
{
	......
}
#include<iostream>
using namespace std;
class Complex
{
public:
	double real, imag;
	Complex(double r = 0.0, double i = 0.0) :real(r), imag(i) { }
	Complex operator-(const Complex& c);//成员函数
};
Complex operator+(const Complex& a, const Complex& b)//普通函数
{
	return Complex(a.real + b.real, a.imag + b.imag);//返回一个临时对象
}
Complex Complex::operator-(const Complex& c)
{
	return Complex(real - c.real, imag - c.imag);//返回一个临时对象
}
//重载为成员函数时,参数个数为运算符数目减一。
//重载为普通函数时,参数个数为运算符数目。

int main()
{
	Complex a(4, 4), b(1, 1), c;
	c = a + b;//等价于c=operator+(a,b);
	cout << c.real << "," << c.imag << endl;
	cout << (a - b).real << "," << (a - b).imag << endl;//a-b等价于a.operator-(b)
	return 0;
}

5.继承

继承的目的是实现代码的重用

继承和派生的概念

  • 继承:在定义一个新的类B时,如果该类与某个已有的类A相似(指的是B拥有A的全部特点),那么就可以把A作为一个基类,而把B作为基类的一个派生类(也称子类)。
  • 派生类是通过对基类进行修改和扩充得到的。在派生类中,可以扩充新的成员变量和成员函数
  • 派生类一经定义后,可以独立使用,不依赖与基类。
  • 派生类拥有基类的全部成员函数和成员变量,不论是private,protected,public。
  • 在派生类的各个成员函数中,不能访问基类中的private成员

派生类的写法

class 派生类名:public 基类名
{

};

6.多态

虚函数和多态

虚函数

  • 在类的定义中,前面有virtual关键字的成员函数就是虚函数。
class base()
{
	virtual int get();
};
int base::get();
  • virtual关键字只用在类定义里的函数声明中,写函数体时不用。
  • 构造函数和静态成员函数不能是虚函数
  • 虚函数和普通函数的区别,虚函数可以参与多态,普通函数不行
  • 派生类的指针可以赋值给基类指针
  • 通过基类指针调用基类和派生类中的同名虚函数时:
    (1)若该指针指向一个基类的对象,那么被调用是基类的虚函数;
    (2)若该指针指向一个派生类的对象,那么被调用是派生类的虚函数;
    这种机制叫做多态。

代码如下:

#include <iostream> 
using namespace std;

class Shape {
protected:
    int width, height;
public:
    Shape(int a = 0, int b = 0)
    {
        width = a;
        height = b;
    }
    virtual int area()//前面如果没有virtual这个虚函数修饰,就不能体现多态
    {
        cout << "Parent class area :" << endl;
        return 0;
    }
};
class Rectangle : public Shape {
public:
    Rectangle(int a = 0, int b = 0) :Shape(a, b) { }
    int area()
    {
        cout << "Rectangle class area :" << endl;
        return (width * height);
    }
};
class Triangle : public Shape {
public:
    Triangle(int a = 0, int b = 0) :Shape(a, b) { }
    int area()
    {
        cout << "Triangle class area :" << endl;
        return (width * height / 2);
    }
};
// 程序的主函数
int main()
{
    Shape* shape;
    Rectangle rec(10, 7);
    Triangle  tri(10, 5);
    // 存储矩形的地址
    shape = &rec;
    // 调用矩形的求面积函数 area
    shape->area();
    // 存储三角形的地址
    shape = &tri;
    // 调用三角形的求面积函数 area
    shape->area();
    return 0;
}

7.输入输出和模板

8.STL标准库

1.string类
  • string类是模板类,使用string类要包含头文件
  • string对象的初始化:
    1.string s1(“Hello”);
    2.string month = “March”;
    3.string s2(8,‘x’);//8个x
  • string对象的长度用成员函数length()读取;
    string s;
    cout<<s.length()<<endl;
  • string支持getline函数
    string s;
    getline(cin,s);
  • 1.用assign成员函数复制
    string s1(“catpig”),s2;
    s2.assign(s1);//全部复制
    s2.assign(s1,1,3);//部分复制,从下标为1的字符开始复制3个字符
  • 2.单个字符赋值
    s2[5] = s1[3] = ‘a’;
  • 3.逐个访问string对象中的字符
    string s1(“Hello”);
    for(int i=0;i<s1.length(),i+++)
    cout<<s1.at(i)<<endl;//成员函数at会做范围检查,下标运算符[]不做范围检查。
  • 4.用+运算符连接字符串
    string s1(“good”),s2(“morning!”);
    s1+=s2;
    cout<<s1;
  • 5.用成员函数append连接字符串
    string s1(“good”),s2(“morning!”);
    s1.append(s2);
    s2.append(s1,3,s1.size());//从下标为3开始,到s1.size();(s1字符数)
  • 6.用关系运算符比较string的大小
    ==,>,>=,<,<=,!=
    返回值都是bool类型,成立返回true,否则返回false。
  • 7.用成员函数compare比较string的大小
    string s1(“hello”),s2(“hello”),s3(“hell”);
    int f1 = s1.compare(s2);//等于返回0 大于返回1 小于返回-1
  • 8.子串成员函数substr
    s2 = s1.substr(4,5);//下标4开始,5个字符
  • 9.交换 成员函数swap
    s1.swap(s2);//把两者的值互换
  • 10.寻找string中的字符成员函数find()//rfind()从后往前找
    s1.find(“a”);//在s1从前往后找,'a’所在位置的下标
  • 11.删除string中的字符 成员函数erase()
    s1.erase(5);//去掉下标5及以后的字符
  • 12.替换string中的字符 成员函数replace()
    s1.replace(2,3,“haha”);//将s1中下标2开始的3个字符换成"haha"
  • 13.在string中插入字符 成员函数insert()
    s1.insert(5,s2);//将s2插入s1下标5的位置
  • 14.将string类型转换为char类型 s1.c_str()
2.STL基本概念
  • 容器:可以容纳各种数据类型的通用数据结构,是类模板
  • 迭代器:可用于依次存取容器中元素,类似于指针
  • 算法:用来操作容器中的元素的函数模板

容器类型
1.顺序容器
vector , deque , list
2.关联容器
set , multiset , map , multimap
3.容器适配器
stack , queue priority_queue

2.STL Vector容器
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

所恋皆洛尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值