C++笔记3

1. 类的基本概念
(1) C语言和C++的区别
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题;

C++是基于面向对象的(既有面向过程,也有面向对象),关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

面向对象的三大特性:封装、继承、多态

类的定义
使用struct / class

对于struct来说,C语言中,结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数

类中的元素称为类的成员:类中的数据称为类的属性或者成员变量;类中的函数称为类的方法或者成员函数。

class ClassName {
	// 类体:由成员函数和成员变量组成
}; //分号一定要有

C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。

public修饰的成员在类外可以直接被访问

protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)

访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止

class的默认访问权限为private,struct为public(因为struct要兼容C)

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用::作用域解析符指明成员属于哪个类域。
class Vehicle {
public:
	void PrintVehicleInfo();
private:
	char _plate_num[20];
	char _vehicle_model[10];
	int  _plate_num;
};

// 这里需要指定PrintVehicleInfo是属于Vehicle这个类域
void Vehicle::PrintVehicleInfo() {
	cout << _plate_num << " "_vehicle_model << " " << _plate_num << endl;
}
类对象模型
用类类型创建对象的过程,称为类的实例化
储存方式:
#include <iostream>

using namespace std;

// 类中既有成员变量,又有成员函数
class A1 {
public:
	void f1() {}
private:
	int _a;
};
// 类中仅有成员函数
class A2 {
public:
	void f2() {}
};
// 类中什么都没有---空类
class A3
{};

int main()
{
	A1 a1;
	A2 a2;
	A3 a3;
	cout << "A1_size: " << sizeof(a1) << endl;
	cout << "A2_size: " << sizeof(a2) << endl;
	cout << "A3_size: " << sizeof(a3) << endl;
	return 0;
}
构造函数和析构函数的基本语法:
构造函数 :
C++中的类需要定义与类名相同的特殊成员函数时, 这种与类名相同的成员函数叫做构造函数;
构造函数可以在定义的时候有参数;
构造函数没有任何返回类型。
构造函数的调用 : 一般情况下, C++编译器会自动的调用构造函数。特殊情况下, 需要手工的调用构造函数。
	class Test
{
public:
	//构造函数
	Test()
	{

	}
}

析构函数:
C++中的类可以定义一个特殊的成员函数清理对象, 这个特殊的函数是析构函数;
析构函数没有参数和没有任何返回类型;
析构函数在对象销毁的时候自动调用;
析构函数调用机制: C++编译器自动调用。
	class Test
{
	~Test()
	{

	}
}
浅拷贝是让两个指针指向同一个位置,而深拷贝是让另一个指针自己再开辟空间。
#include<bits/stdc++.h>
using namespace std;
class Student {
	int name;
	int* p;
public:
	~Student() {
		//cout << p << endl;
		delete p; //delete只能和New连用,这里p也是New出来的。
		cout << "删除完毕" << endl;
	}
	Student() {
		p = new int();
	}
};
int main() {
	Student a = *(new Student());
	Student b(a); //拷贝复制过来 这是浅拷贝 指向一个位置
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
class Student {
	int name;
	int* p;
public:
	~Student() {
		//cout << p << endl;
		delete p; //delete只能和New连用,这里p也是New出来的。
		cout << "删除完毕" << endl;
	}
	Student() {
		p = new int();
	}
	Student(const Student& a) {
		name = a.name;
	}
};
int main() {
	Student a = *(new Student());
	Student b(a); //拷贝复制过来 这是浅拷贝 指向一个位置
	return 0;




this指针
(1) 访问成员函数
#include <iostream>

using namespace std;

class Date
{
public:
	void Display()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	void SetDate(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

int main()
{
	Date d1, d2;
	d1.SetDate(2018, 5, 1);
	d2.SetDate(2018, 7, 1);
	d1.Display();
	d2.Display();
	return 0;
}

初始化列表:
与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段。
class foo
{
public:
	foo(string s, int i) :name(s), id(i) {}; // 初始化列表
private:
	string name; int id;
};
初始化阶段
所有类类型(class type)的成员都会在初始化阶段初始化,即使该成员没有出现在构造函数的初始化列表中.

计算阶段
一般用于执行构造函数体内的赋值操作。
class Test1
{
public:
	Test1() // 无参构造函数
	{
		cout << "Construct Test1" << endl;
	}
	Test1(const Test1& t1) // 拷贝构造函数
	{
		cout << "Copy constructor for Test1" << endl; this->a = t1.a;
	}
	Test1& operator = (const Test1& t1) // 赋值运算符
	{
		cout << "assignment for Test1" << endl; this->a = t1.a; return *this;
	}
	int a;
};
class Test2
{
public:
	Test1 test1;
	Test2(Test1 &t1)
	{
		test1 = t1;
	}
};
成员变量的顺序
class foo
{
public:
	int i; int j;
	foo(int x) :i(x), j(i) {}; // ok, 先初始化i,后初始化j
};
什么是static ?
static 是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性。
引用静态数据成员时,采用如下格式:
<类名>::<静态成员名>
如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员。
const
const 是 constant 的缩写, 是不变的意思.在 C++ 中是用来修饰内置类型变量, 自定义对象, 成员函数, 返回值, 函数参数. const 可以帮我们避免无意之中的错误操作.
常对象
类名 const 对象名
const 类名 对象名
常对象必须要有初始值
Time const t1(12, 34, 46);
const Time t1(12, 34, 46);

C++运算符重载
运算符的重载,实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该运算符时就调用此函数来行使运算符功能。这个函数叫做运算符重载函数(常为类的成员函数)。
用函数的方式实现了( + -*/ []数组 && || 逻辑 等)运算符的重载。
运算符重载的两种方法
1二元运算符重载
类内重载
#include <iostream>
using namespace std;

class Point {
public:
	Point() {};
	Point(int x, int y) : x(x), y(y) {};
	Point operator+(const Point &b) { //类内重载,运算符重载函数作为类的成员函数
		Point ret;
		ret.x = this->x + b.x;
		ret.y = this->y + b.y;
		return ret;
	}
	int x, y;
};

int main() {
	Point a(2, 4), b(5, 3);
	Point c = a + b;      //这里c++编译器会,自动去找 + 运算符的重载函数
	cout << "x :" << c.x << endl;
	cout << "y :" << c.y << endl;
}

#include <iostream.h>
class Point
{
public:
	void output()
	{
	}
	static void init()
	{
	}
};
void main(void)
{
	Point pt;
	pt.init();
	pt.output();
}
类外重载(用友元函数的方法实现)
#include <iostream>
using namespace std;

class Point {
public:
	Point() {};
	Point(int x, int y) : x(x), y(y) {};
	friend Point operator+(const Point &, const Point &);   //声明类的友元函数
	int x, y;
};

Point operator+(const Point &a, const Point &b) {//类外重载,运算符重载函数作为类的友元函数
	Point ret;
	ret.x = a.x + b.x;
	ret.y = a.y + b.y;
	return ret;
}

int main() {
	Point a(2, 4), b(5, 3);
	Point c = a + b;
	cout << "x :" << c.x << endl;
	cout << "y :" << c.y << endl;
}
= 等号运算符重载
#include <iostream>
using namespace std;

class  Name
{
public:

	//main函数中的问题   Name obj2 = obj1;  
	//解决方案: 手工的编写拷贝构造函数 使用深copy
	Name(const Name& obj)
	{
		m_len = obj.m_len;
		m_p = (char *)malloc(m_len + 1);
		strcpy(m_p, obj.m_p);
	}

	//等号运算符重载函数
	Name& operator=(Name &obj)
	{
		//1.先释放旧的内存
		if (this->m_p != NULL)
		{
			delete[] m_p;
			m_len = 0;
		}
		//2.根据obj分配内存大小
		this->m_len = obj.m_len;
		this->m_p = new char[m_len + 1]; //加1,结束符'\n'。

		//3.把obj赋值
		strcpy(m_p, obj.m_p);  //字符串的拷贝函数
		return *this;
	}

	~Name()    //析构函数
	{
		if (m_p != NULL)
		{
			free(m_p);
			m_p = NULL;
			m_len = 0;
		}
	}
protected:
private:
	char *m_p;
	int m_len;
};

void main()
{

	Name obj1("abcdefg");
	Name obj2 = obj1;  //C++编译器提供的 默认的copy构造函数  浅拷贝,需要手工编写构造函数
	Name obj3("obj3");

	obj1 = obj2 = obj3;    //调用等号运算符重载
	cout << "hello..." << endl;
	system("pause");
	return;
}

this指针的特性
this指针的类型:类类型* const
只能在“成员函数”的内部使用
this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this
形参。所以对象中不存储this指针。
this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户
传递

#include <iostream>

using namespace std;

class A
{
public:
	void PrintA()
	{
		cout << _a << endl;
	}

	void Show()
	{
		cout << "Show()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = NULL;
	p->PrintA();
	p->Show();
}

继承:继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,
这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程,以前我们接触的复用都是函数复用,继承是类设计层次的复用。
1定义格式
//     派生类   继承方式  基类
class Student : public Person
{
protected:
	int _stuid;
};
继承关系的访问限定符
继承方式:public继承、protected继承、private继承。

访问限定符:public访问、protected访问、private访问。
//将派生类的应用,指针赋值给父类
#include<iostream>
using namespace std;
class Person
{
public:
	string name = "Peter";
	int age = 18;
};
class Student :public Person
{
public:
	int id = 0;
};
int main()
{
	Student s;
	s.name = "Hello";
	s.age = 10;
	s.id = 20101320;
	Person p;
	p = s;//将派生类的值赋值给父类
	Person* prt = &s;//父类的指针可以指向派生类
	Person& inference = p;//引用

	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值