从c到c++(2) 1.类的定义 2.构造函数与析构函数 3.访问控制与接口 4.拷贝:拷贝构造函数 5.类模板:我们可以将一个类变成类模板或模板类,正如一个模板函数一样 6.string 7.继承:一个派生类从1个或多个父类继承,既继承父类的属性和行为,但也有自己的特有属性和行为

c++的struct是在c的struct类型上,增加了成员函数
c的struct可将一个概念或实体的所有属性组合在一起,描述同一类对象的共同属性
c++使struct不但包含数据,还包含函数用于访问或修改变量

#include <iostream>
#include <cmath>
using namespace std; 

struct Date{
	int d, m, y;
	void init(int dd, int mm, int yy){ 
		d = dd;
		m = mm;
		y = yy; 
	} 
	void print(){
		cout << y << "-" << m << "-" << d << endl; 
	}
	Date& add(int dd){
		d = d + dd;
		return *this; // this是指向这个函数的类型对象指针
		// *this解引用,是这个函数的对象
		// 这个函数返回的是自引用。可以实现链式调用 
	} 
	// 成员函数重载+=运算符实现更直观的add 
	Date& operator+= (int dd) {
		d = d + dd;
		return *this; 
	} 
};
int main(){
	Date day;
	day.print();
	day.init(4, 6, 1999);
	day.add(1).add(1); 
	(day += 1) += 1; 
	day.print();
} 

2.构造函数与析构函数

#include <iostream>
#include <cstring>

using namespace std; 

struct Person{
	int age;
	char *name; 
	// 构造函数。注:构造函数可以重载 
	Person(char *n = "on_name", int a = 0){
		int len = strlen(n);
		// 申请内存 
		name = new char[len + 1]; // +1给 留位置 
		strcpy(name, n); // 字符串拷贝 
		age = a;
		cout << "构造完毕" << endl;
	}
	// 析构函数
	virtual ~Person(){
		// 释放内存 ,防止内存泄漏 
		delete[] name; 
		cout << "析构完毕" << endl;
	}
};
int main(){
	Person p("小明", 5);
	cout << p.name << "--" << p.age << endl;
} 

3.访问控制与接口

class比struct多了访问控制与接口

#include <iostream>
#include <cstring>

using namespace std; 

// 把struct改成class之后要用public修饰才能达到和之前一样的效果,不然回报错,因为class里面的成员变量和成员函数默认是private的 
class Person{
// public:之后的成员函数和成员变量是公开的 
public: 
	int age;
	char *name; 
	// 构造函数。注:构造函数可以重载 
	Person(char *n = "on_name", int a = 0){
		int len = strlen(n);
		// 申请内存 
		name = new char[len + 1]; // +1给 留位置 
		strcpy(name, n); // 字符串拷贝 
		age = a;
		cout << "构造完毕" << endl;
	}
	// 析构函数
	virtual ~Person(){
		// 释放内存 ,防止内存泄漏 
		delete[] name; 
		cout << "析构完毕" << endl;
	}
};
int main(){
	Person p("小明", 5);
	cout << p.name << "--" << p.age << endl;
} 

4.拷贝:拷贝构造函数

硬拷贝带来的问题

#include <iostream>
#include <cstring>

using namespace std; 

class Person{
public: 
	int age;
	char *name; 
	// 构造函数。注:构造函数可以重载 
	Person(char *n = "on_name", int a = 0){
		int len = strlen(n);
		// 申请内存 
		name = new char[len + 1]; // +1给 留位置 
		strcpy(name, n); // 字符串拷贝 
		age = a;
		cout << "构造完毕" << endl;
	}
	// 析构函数
	virtual ~Person(){
		// 释放内存 ,防止内存泄漏 
		delete[] name; // 由于硬拷贝,p和p1的name指向同一块内存,而它们的析构函数分别会执行一次,所以会对同一块内存释放两次 ,从而出错 ,解决方案如下 
		cout << "析构完毕" << endl;
	}
	
	// 解决上述硬拷贝带来的问题,重写拷贝构造函数,实现浅拷贝
	Person(Person &p){
		age = p.age;
		// 让拷贝构造函数的成员不指向同一块内存,从而避免析构函数对同一块内存释放两次的问题 
		int len = strlen(p.name);
		name = new char[len + 1]; // +1给 留位置 
		strcpy(name, p.name); // 字符串拷贝 
	} 
};
int main(){
	Person p("小明", 5);
	// 调用拷贝构造函数 ,如不重写该构造函数,属于硬拷贝 
	Person p1(p);
	cout << p.name << "--" << p.age << endl;
	cout << p1.name << "--" << p1.age << endl;
} 

5.类模板:我们可以将一个类变成类模板或模板类,正如一个模板函数一样

#include <iostream>
using namespace std; 

// 类模板实现数组存放所有的类型 
template <class T> 
class Array{
	int size;
	T *data;
public: 
	Array(int s){
		// 数组长度 
		size = s;
		// 数组的数据 
		data = new T[s];
	}
	// 析构函数
	~Array(){
		delete[] data; 
	}
	// 运算符重载
	T& operator [](int i){
		if(i < 0 || i >= size){
			cout << "err"; 
			throw "out of index"; 
		}
		return data[i];
	}
	// 遍历数组
	void show(){
		for(int i = 0; i < size; i++){
			cout << data[i] << endl;
		}
	} 
};

int main(){
	int n = 2;
	// <int> 表示 T是int类型 
	Array<int> t(n);
	t[0] = 1;
	// 两次利用了运算符重载,实现了数组使用键赋值和获取值 
	t[1] = t[0] + 1;
	// t[2] = 3; 会触发错误 
	t.show();
} 

6.string

#include <iostream>
#include <string>
#include <vector>
using namespace std; 

int main(){
	// string对象的初始化 
	string s("HELLO");
	s = "DEMO"; // 赋值运算符 
	
	// 常量迭代器
	string::const_iterator cii;
	int ii = 0;
	for(cii = s.begin(); cii != s.end(); cii++){
		cout << ii++ << " " << *cii << endl;
	}
	
	// 向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container) 
	// 跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。
	vector<int>obj;//类模板的使用方法,创建一个向量存储容器 int
	for(int i=0;i<10;i++) // push_back(elem)在数组最后添加数据 
    {
        obj.push_back(i);
        cout<<obj[i]<<",";    
    }
} 

7.继承:一个派生类从1个或多个父类继承,既继承父类的属性和行为,但也有自己的特有属性和行为

#include <iostream>
#include <string>
#include <vector>
using namespace std; 

class Person{
public: 
	string name;
	void say(){
		cout << "i am " << name;
	}
}; 
class Teacher: public Person{
public: 
	Teacher(string n){
		name = n;
	}
};

int main(){
	Teacher a("白白");
	a.say(); 
}