day2
二、类和对象
1.类基础
class.cpp
#include <iostream>
using namespace std;
/*
1.类体中默认权限为:private
2.成员函数在类体之外的定义语法:
数据类型 类名::函数名(<参数列表>){ 函数体 }
3.成员变量的作用域:
整个类的作用域( 类域 ):类的所有成员函数的函数体区域
4.类的所有成员函数都有一个特殊的指针:this ,指向访问当前成员函数的对象
5.类:
代码角度:用户自定义的数据类型,由class进行说明
抽象角度:对象的类型,是一批对象的共性和特征,是对象的抽象概括
6.对象:
代码角度:就是一个变量
抽象角度:具备行为和属性的事物,一切皆为对象,也是类的实例
7.OOP思想:面向对象程序设计
1) 抽象:就是声明一个类,抽象概括出一类对象的公共性质
数据抽象:设置成员变量
代码抽象:设置成员函数
2) 封装:将数据成员和成员函数结合在一起,形成一个整体,就是类体部分
*/
class Student{ //声明定义 Student 类
public:
void setValue(char, int); //成员函数的声明
private:
char sex;
int age;
};
void Student::setValue(char sex, int age){ //成员函数的定义
this->sex = sex;
this->age = age;
}
int main(int argc, char *argv[]){
class Student stu; //定义一个对象,实质是定义一个变量
//stu.age = 18; //私有变量不能直接访问
stu.setValue(1, 4);
class Student *stu1; //定义一个对象指针,实质是定义一个指针
Student stu2; //class 关键字可以省略
Student *stu3;
stu1 = &stu;
stu3 = new Student; //开辟一个堆区空间,首地址给stu3
stu1->setValue(2, 3); //对象指针访问成员使用 ->
return 0;
}
2.简单的学生类
studentClass.cpp
#include <iostream>
using namespace std;
class Student{
public:
void setValue(int, float);
int getAget();
float getWeight();
private:
int age;
float weight;
};
void Student::setValue(int age, float weight){
this->age = age;
this->weight = weight;
}
int Student::getAge(){
return age;
}
float Student::getWeight(){
return weight;
}
int main(int argc, char *argv[]){
Student stu; //定义一个对象
stu.setValue(18, 120);
Student stu1;
stu1 = stu; //默认赋值运算
cout << stu1.getAge() << endl; //18
Student *p;
p = &stu; //默认地址运算
cout << p->getWeight() << endl; //120
Student stu2 = stu1; //默认拷贝构造
cout << stu2.getAge() << endl; //18
Student stu3(stu1); //默认拷贝构造
cout << stu3.getAge() << endl; //18
Student *q = new Student;
return 0;
}
3.构造函数
constructor.cpp
#include <iostream>
#define pri() cout<<"line "<<__LINE__<<endl;
using namespace std;
/*
构造函数的目的:初始化对象
语法:
类名::类名(){ 函数体 }
特点:
1) 没有显示说明时,自动生成默认构造函数
2) 构造函数没有数据类型,没有返回值
3) 构造函数函数名与类名一致
4) 构造函数只能在定义对象时被系统自动调用
5) 构造函数可以重载
6) 构造函数可以有默认参数
7) 构造函数是类的特殊成员函数
8) 构造函数一般声明在public区域,也可声明在protected和private区域形成限制构造
*/
class Student{
public:
Student(); //默认无参构造函数显式说明
Student(int); //有参构造函数显式说明,此时无参构造将不会自动生成
Student(Student &obj); //拷贝构造显式说明
private:
int age;
float weight;
};
Student::Student(){
pri();
cout << "默认无参构造" << endl;
}
Student::Student(int i){
pri();
cout << "默认有参构造" << endl;
}
Student::Student(Student &obj){
pri();
cout << "默认拷贝构造" << endl;
}
int main(int argc, char *argv[]){
Student stu; //定义一个对象,采用默认构造,没有显示说明时,编译器自动生成
Student stu1(1); //默认有参构造
Student stu3(stu1); //默认拷贝构造
Student stu2 = stu1; //默认拷贝构造
Student *q = new Student; //默认无参构造 new对象时一定会调用构造函数
q = new Student(2); //默认有参构造
q = new Student(stu); //默认拷贝构造
return 0;
}
4.对象成员
objectMember.cpp
#include <iostream>
#define pri() cout<<"line "<<__LINE__<<endl;
using namespace std;
class A{
public:
A(){ pri(); }
A(A &obj){ pri(); }
};
class B{
public:
B(){ pri(); }
};
class Demo{
public:
B c;
Demo(){ pri(); }
private:
A a;
A b;
};
int main(int argc, char *argv[]){
Demo obj;
return 0;
}
5.拷贝构造
浅拷贝 shallowCopy.cpp
#include <iostream>
#include <string.h>
#define pri() cout<<"line "<<__LINE__<<endl;
using namespace std;
class Student{
public:
Student(const char *, int);
Student(Student &obj);
void setName(const char *);
char * getName();
private:
char *name; //野指针使用之前开空间
int age;
};
Student::Student(const char *name, int age){
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->age = age;
}
Student::Student(Student &obj){
this->name = obj.name; //浅拷贝:两个对象的成员指针,指向同一个堆区空间,两个成员指针相互干扰
this->age = obj.age;
}
void Student::setName(const char *name){
strcpy(this->name, name);
}
char * Student::getName(){
return name;
}
int main(int argc, char *argv[]){
Student stu("张三", 18);
Student stu1(stu);
cout << stu1.getName() << endl; //张三
stu1.setName("张三疯");
cout << stu.getName() << endl; //张三疯
return 0;
}
深拷贝 deepCopy.cpp
#include <iostream>
#include <string.h>
#define pri() cout<<"line "<<__LINE__<<endl;
using namespace std;
class Student{
public:
Student(const char *, int);
Student(Student &obj);
void setName(const char *);
char * getName();
private:
char *name; //野指针使用之前开空间
int age;
};
Student::Student(const char *name, int age){
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->age = age;
}
Student::Student(Student &obj){
this->name = new char[strlen(obj.name) + 1]; //深拷贝:两个对象的成员指针,指向两个不同的堆区,互不干扰
strcpy(this->name, obj.name);
this->age = obj.age;
}
void Student::setName(const char *name){
strcpy(this->name, name);
}
char * Student::getName(){
return name;
}
int main(int argc, char *argv[]){
Student stu("张三", 18);
Student stu1(stu);
cout << stu1.getName() << endl; //张三
stu1.setName("张三疯");
cout << stu.getName() << endl; //张三
return 0;
}
6.析构函数
destructor.cpp
#include <iostream>
#include <string>
using namespace std;
#define pri() cout<<"line:"<<__LINE__<<endl;
/*
析构函数:回收对象占用的资源
1.没有数据类型,没有返回值
2.函数名由~类名构成
3.没有参数
4.对象生命周期结束时,系统自动调用
5.对象指针遇见delete时,系统自动调用
*/
/*
包含对象成员(另一个类的对象作为该类的成员变量)的类对象的构造析构顺序
对象成员构造->对象构造->对象析构->对象成员析构
*/
class Base{
public:
Base(){
p = new char[12];
pri();
cout << "默认构造函数" << endl;
}
~Base(){ //析构函数
delete [] p;
cout << "默认析构函数" << endl;
}
private:
char *p;
};
int main()
{
Base obj;
Base *p = new Base; //堆区空间不会随着程序结束而结束
delete p;
return 0;
}
小练习
/*
设计一个Point类描述坐标点,定义p1点(0,4),p2点(3,0)。
计算两点之间的直线距离,要求用以下函数输出结果:
cout << p1.dis(p2) << endl;
*/
注:
引入头文件
#include <math.h>
或者
#include <cmath>
平方:
pow(x,2)
开平方根:
sqrt(x)
两点间距离公式
d
=
(
x
2
−
x
1
)
2
+
(
y
2
−
y
1
)
2
d = \sqrt{(x_{2}-x_{1})^2+(y_{2}-y_{1})^2}
d
=
(
x
2
−
x
1
)
2
+
(
y
2
−
y
1
)
2