C++入门(2)
欢迎加入QQ:498903810 一起交流、讨论知识,里面有大佬,也有小白,天下码农一家亲,大家一起讨论进步。
1.认识类和对象
万物皆对象,这个对象不是你的女票呦,类之于对象,数据类型之于变量.
例:
class Student //这是定义了一个类,但是这个类里面什么都没写
{
public:
protected:
private:
};
Student s1; //用这个类定义了一个对象 s1
int a; //学过C语言的都知道这是定义了一个整型变量 a
类比的记忆是不是可以加深我们对C++的学习呀,我们再来回忆一下C语言定义一个结构体和用结构体定义一个变量。
例:
typedef struct Student
{
int a;
}Student;
Student s1;
结构定义变量和类实例化对象是不是很类似,实例化就是定义对象的那个过程。所以来说知识换汤不换药,大家听到陌生的名词不必惊讶,接下来继续深入的为大家介绍C++。
- 面向对象四大特征(偷来的表格)
特征 | 说明 | 类比 |
---|---|---|
抽象 | 抽出具体事物的普遍性的本质 | 分门别类:鸟类、哺乳类、鱼类 |
封装 | 把数据与处理(函数)包在一起 | 通信录(增加、删除) |
继承 | 数据与处理(函数)的传承 | 财富与绝技、混血儿(肤色/头发、 两种语言 |
多态 | 同一个事物(函数)的多种形态 | 手机键盘数字与字母、 电脑键盘功能键 |
注:一般也分为三大特征,不包含抽象。
2.深入理解类
类里面可以定义变量还可以写方法,方法就是函数的意思。
例:
class Student //这是定义了一个类,但是这个类里面什么都没写
{
public:
void Print()
{
cout << "hello world" << endl;
}
protected:
private:
};
Student s1;
s1.Print();
输出结果:
hello world
上面在类Student里面写了一个Print()方法(函数),它的功能就是输出一条语句。
那么我们来介绍一下类里面写的东西吧
public:
protected:
private:
这三个对类内的方法/属性起到访问控制的作用,主要体现了C++的封装特性,封装有两层含义:
1.把属性和方法进行封装。
2.对属性和方法进行访问控制。
分类 | 特征 |
---|---|
public | 类的外面可以访问该属性的函数/变量 |
protected | 主要用于继承的函数或者变量(后面会提到) |
private | 类的私有函数/变量,类的外面不能访问 |
打一个比方来说这个三个属性:
public:相当于你上学用的铅笔可以借给别人使用
protected:某个作坊的秘制配方,只能用来传给下一代,不能被别人知道
private:相当于你的银行卡密码谁都不能告诉,包括你的儿子,万一要是他拿去打赏主播就不太好了,
所以谁都不能告诉。别人也无权知道
3.对象的创建
1.对象的创建和初始化
#include<iostream>
#include<string>
using namespace std;
class Student
{
public:
int age;
string name;
};
Student s1, s2, s3, s4;
s1.age = 0; s1.name = "";//对象进行初始化
s2.age = 0; s2.name = "";
s3.age = 0; s3.name = "";
s4.age = 0; s4.name = "";
这样初始化是不是很麻烦啊,有没有一种简便的方法,可以批量初始化,或者在定义变量的时候初始化呢???
答案是当然有的:C++为我们提供了,构造函数构造函数就是在定义变量的时候调用进行初始化.
前面写那么多次的初始化,但是如果你写了一个无参的构造函数那么就可以不用每次辛苦的手动初始化了。
# include<iostream>
# include<string>
using namespace std;
class Student
{
public:
Student()
{
age = 0;
name = “”;
}
Student Return()
{
Student tmp;
tmp.age = 10;
tmp.name = "zhangsan";
}
int age;
string name;
};
Student s1, s2, s3, s4;
2.匿名对象
匿名对象就是返回一个栈的对象。
如果匿名对象没有用于初始化别的对象或者给别的对象赋值,那么匿名对象就会被析构掉,就是被编译器释放。
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student()
{
this->age = 0;
this->name = "";
}
Student Return()//返回一个匿名对象
{
Student tmp;//在栈中定义的变量
tmp.age = 12;
tmp.name = "zhangsan";
return tmp;
}
void Print()//打印信息
{
cout << "age = " << this->age<< endl;
cout << "name = "<< this->name << endl;
}
int age;
string name;
};
int main()
{
Student s1;
Student s2;
s2 = s1.Return();//用s2接收,s1.Return()返回的匿名对象
s2.Print();//打印s2的信息
return 0;
}
输出结果:
age = 12
name = zhangsan
3.动态对象
动态对象就是你用new在堆上定义的变量,new类似于C语言的malloc()函数,而释放堆上的内存空间C++用的是delet,与之对应的C语言的是free。C++用new申请的内存,最好用delete释放,但是也可以用free释放,同样,malloc的内存也可以用delete释放,但是不建议,也不允许这样做。后面会讲到,但是可以先说一点。new申请内存会调用该对象的拷贝构造函数,delete会调用该对象的析构函数。
举个栗子:
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
class Student
{
public:
Student()
{
this->age = 0;
this->name = "";
}
void Print()
{
cout << "age = " << this->age<< endl;
cout << "name = "<< this->name << endl;
}
int age;
string name;
};
int main()
{
Student * s1 = new Student;//new申请内存空间
Student * s2 = new Student;//new申请内存空间
Student * s3 = (Student *)malloc(sizeof(Student));//new申请内存空间
Student * s4 = (Student *)malloc(sizeof(Student));//new申请内存空间
delete s1;//new申请内存空间, 用delete释放
free(s2);//new申请内存空间, 用free释放--->不建议,不支持,不允许这样用
delete s3;//malloc申请内存空间, 用delete释放--->不建议,不支持,不允许这样用
free(s4);//new申请内存空间, 用free释放
return 0;
}
程序没有输出,但是程序可以成功执行,没有报错没有警告。
4.对象数组
对象数组就行定义一个数组,定义和上一个例子类似
两点区别:
Student * s1 = new Student[5];//new申请内存空间
delete []s1;注:
申请时在后面加[num],num为你要申请的数组的长度
释放内存空间的时候在前面需要加一个[]
4.默认构造函数
1.构造函数
1.默认构造函数
文件的默认构造函数主要的目的就是为了初始化变量,就不用每次都手动的去初始化,前面也讲过了
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
class Student
{
public:
Student()
{
cout << "我是默认拷贝函数" << endl;
}
};
int main()
{
Student s1, s2, s3, s4;
return 0;
}
输出结果:
我是默认拷贝函数
我是默认拷贝函数
我是默认拷贝函数
我是默认拷贝函数
2.拷贝构造函数
拷贝构造函数的调用时机是用一个对象初始化另一个对象的时候。
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
class Student
{
public:
Student()
{
cout << "我是默认拷贝函数" << endl;
}
Student(const Student &obj)
{
cout << "我是拷贝构造函数" << endl;
}
};
int main()
{
Student s1;
Student s2 = s1;
Student s3 = s2;
system("pause");
return 0;
}
运行结果:
我是默认拷贝函数
我是拷贝构造函数
3.有参构造函数
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
class Student
{
public:
Student()
{
num = 0;
cout << "我是默认拷贝函数" << endl;
}
Student(int a)
{
num = a;
cout << "我是有参的拷贝构造函数" << endl;
}
Student(const Student &obj)
{
num = obj.num;
cout << "我是拷贝构造函数" << endl;
}
private:
int num;
};
int main()
{
Student s1;
Student s2(2);
Student s3 = s2;
system("pause");
return 0;
}
运行结果:
我是默认拷贝函数
我是有参的拷贝构造函数
我是拷贝构造函数
2.初始化列表
语法
c++ 类名(参数):成员变量(参数){ 函数体 }
作用
初始化非静态成员变量
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
class Student
{
public:
Student()
{
num = 0;
cout << "我是默认拷贝函数" << endl;
}
Student(int a):num(a)//和num = a是一样的作用
{
cout << "我是有参的拷贝构造函数 num = "<< num << endl;
}
Student(const Student &obj):num(obj.num)//和num = obj.num是一样的作用
{
cout << "我是拷贝构造函数 num = " << num << endl;
}
private:
int num;
};
int main()
{
Student s1;
Student s2(2);
Student s3 = s2;
system("pause");
return 0;
}
运行结果:
我是默认拷贝函数
我是有参的拷贝构造函数 num = 2
我是拷贝构造函数 num = 2
3.成员变量的初始化顺序
这个就一句话:谁先定义谁先初始化
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
class Test1
{
public:
Test1()
{
cout << "我是测试一的构造函数" << endl;
}
};
class Test2
{
public:
Test2()
{
cout << "我是测试二的构造函数" << endl;
}
};
class Test3
{
public:
Test3()
{
cout << "我是测试三的构造函数" << endl;
}
};
class Student
{
public:
Student():t1(), t2(), t3()//正序初始化
{
}
private:
Test3 t3;//逆序定义
Test2 t2;
Test1 t1;
};
int main()
{
Student s1;//会调用拷贝构造函数
system("pause");
return 0;
}
运行结果:
我是测试三的构造函数
我是测试二的构造函数
我是测试一的构造函数