3.C++远征--封装篇
3.1 类和对象
3.1.1 对象是具体的事物,类则是从对象中抽象出来的
类:数据类型的全部属性,对象是根据这些描述创建的文件
类的定义:
关键字--class TV--类名
{
char name[20];
属性---- int age; ------ 数据成员
int type;
方法--- void changeVol(); ---成员函数
void power();
};
目的不同,从同一个对象中抽样出的类不同,在描述一个类的时候,需要在类里面罗列出详细 信息,但是我们不能全部把信息都给使用者,所以要选择性暴露,在C++中就有了访问限定符的东西:
public : 公共的(希望暴露)
protect : 受保护的
private : 私有的(希望隐藏)
3.1.2 对象实例化
1) 从栈实例化
关键字--class TV--类名 int main()
{ {
char name[20];
属性---- int age; ------ 数据成员 TV tv;
int type; TV tv[20];
方法--- void changeVol(); ---成员函数
void power(); return 0;
}; }
2)从堆实例化
关键字--class
TV--类名 int main()
{
{
char name[20]; TV *p = new TV();
属性---- int age; ------ 数据成员 TV *q = new TV[20];
int type;
// to do
delete p;
方法--- void changeVol(); ---成员函数 delete [ ]q;
void power();
return 0;
}
; }
3.1.3 对象成员的访问
栈的访问: 堆的访问:
int mian () int mian ()
{ {
TV tv; TV *p = new TV();
tv.type = 0; p ->type = 0;
tv.changeVol(); p ->changeVol();
return 0; delete p;
} p = NULL;
return 0;
}
代码演示:
#include<stdlib.h>
#include<iostream>
using namespace std;
class Coordinate
{
public:
int x;
int y;
void printx()
{
cout << x << endl;
}
void printy()
{
cout << y << endl;
}
};
int main()
{
Coordinate coor;
coor.x = 10;
coor.y = 20;
coor.printx();
coor.printy();
Coordinate *p = new Coordinate();
if (NULL == p)
{
system("pause");
return 0;
}
p->x = 100;
p->y = 200;
p->printx();
p->printy();
delete p;
p = NULL;
system("pause");
return 0;
}
3.2 字符串类型string
string 类型
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
string name ="zhangsan";
string hobby ("football");
cout<<
name<<
hobby<<endl;
return 0;
}
初始化string对象的方式:
string s1; s1是空串
string s2("ABC"); 用字符串字面值初始化s2
string s3(s2); 将s3初始化为s2的一个副本
string s4(n,‘c') 将s4初始化为字符c的n个副本
代码示例:
/*******************************************************************/
/* 题目描述:
1.提示用户输入姓名
2.接收用户的输入
3.然后向用户问好,hello xxx
4.告诉用户名字的长度
5.告诉用户名字的首字母是什么
6.如果用户直接输入回车,那么告诉用户输入的为空
7.如果用户输入的是imooc,那么告诉用户的角色是一个管理员*/
/*******************************************************************/
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;
int main()
{
string name;
cout << "input your name:";
getline(cin, name);
if (name.empty())
{
cout << "input is empty" << endl;
system("pause");
return 0;
}
if (name == "imooc")
{
cout << "you are a administrator" << endl;
}
cout << "Hello " << name << endl;
cout << "your name length is:"<< name.size() << endl;
cout << "your name first letter is:" << name[0] << endl;
system("pause");
return 0;
}
单元巩固:定义一个student类,包含名字和年龄两个数据成员,实例化一个student对象,并打印出其两个数据成员
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;
class student
{
public:
int age;
string name;
};
int main()
{
student stu;
stu.name = "慕课网";
stu.age = 2;
cout << stu.name << " age is:" << stu.age << endl;
system("pause");
return 0;
}
3.3数据封装之初始封装
面向对象的基本思想:以对象为中心,以谁做什么来表达程序的逻辑,转化为代码层面就是把所有的数据操作通过函数的调用来完成。
若将数据成员写进public,直接进行调用,就好像原始人吃肉,营养不高,不卫生,所有用封装来解决。
代码演示:
/*定义一个学生的类,含如下信息:
1.姓名:name
2.性别:gender
3.学分(只读):score
4.学习:study */
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;
class student
{
public:
void setName(string _name)
{
m_strName = _name;
}
string getName()
{
return m_strName;
}
void setGender(string _gender)
{
m_strGender = _gender;
}
string getGender()
{
return m_strGender;
}
int getScore()
{
return m_iScore;
}
void initScore()
{
m_iScore = 0;
}
void study(int _score)
{
m_iScore += _score;
}
private:
int m_iScore;
string m_strName;
string m_strGender;
};
int main()
{
student stu;
stu.initScore();
stu.setName ("张三");
stu.setGender ("女");
stu.study(5);
stu.study(3);
cout << stu.getName() << " " << stu.getGender() << " " <<stu.getScore()<< endl;
system("pause");
return 0;
}
注:在编辑是错把变量 _score 写进getScore(int _score)里导致一直编译错误,并且在这里就对变量名的设置有了一定的要求如上所示!
单元巩固:定义一个student类,包含名字一个数据成员,使用get和set函数封装名字这个数据成员。在main函数中通过new实例化对象,并打印其相关函数。
/*定义一个学生的类,含如下信息:
1.姓名:name
2.性别:gender
3.学分(只读):score
4.学习:study */
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;
class student
{
public:
void setName(string _name)
{
m_strName = _name;
}
string getName()
{
return m_strName;
}
void print()
{
cout << m_strName << endl;
}
private:
string m_strName;
};
int main()
{
student *stu = new student();
if (NULL == stu)
{
system("pause");
return 0;
}
stu->setName ("张三");
stu->getName();
stu->print();
delete stu;
stu = NULL;
system("pause");
return 0;
}
3.4类内定义
类内定义和内联函数;
类外定义:
同文件类外定义 : 分文件类外定义:
Car.cpp 文件 Car.h 文件 Car.cpp文件
class Car class Car #include "Car.h"
{ { void
Car::run()
public: public: {}
void run(); void run(); void
Car::stop()
void stop(); void stop(); {}
}; };
void
Car::run(){}
void
Car::stop(){}
代码演示:
同文件类外定义:
/*定义一个Teacher类,要求分别采用同文件类外定义和分文件类外定义
的方式完成,具体要求如下:
数据成员:
姓名:name
性别:gender
年龄:age
成员函数:
数据成员的封装函数
授课teach */
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;
class Teacher
{
public:
void setName(string _name);
string getName();
void setGender(string _gender);
string getGender();
void setAge(int _age);
int getAge();
void teach();
private:
string m_strName;
string m_strGender;
int m_iAge;
};
void Teacher::setName(string _name)
{
m_strName = _name;
}
string Teacher::getName()
{
return m_strName;
}
void Teacher::setGender(string _gender)
{
m_strGender = _gender;
}
string Teacher::getGender()
{
return m_strGender;
}
void Teacher::setAge(int _age)
{
m_iAge = _age;
}
int Teacher::getAge()
{
return m_iAge;
}
void Teacher::teach()
{
cout << "现在上课..." << endl;
}
int main()
{
Teacher t;
t.setName("孔子");
t.setGender("男");
t.setAge(30);
cout << t.getName() <<" "<< t.getGender()<<" " << t.getAge() << endl;
t.teach();
system("pause");
return 0;
}
分文件类外定义:
/*定义一个Teacher类,要求分别采用同文件类外定义和分文件类外定义
的方式完成,具体要求如下:
数据成员:
姓名:name
性别:gender
年龄:age
成员函数:
数据成员的封装函数
授课teach */
#include<iostream>
#include<string>
#include"Teacher.h"
using namespace std;
int main()
{
Teacher t;
t.setName("孔子");
t.setGender("男");
t.setAge(30);
cout << t.getName() <<" "<< t.getGender()<<" " << t.getAge() << endl;
t.teach();
system("pause");
return 0;
}
Teacher.h
#include<string>
using namespace std;
class Teacher
{
public:
void setName(string _name);
string getName();
void setGender(string _gender);
string getGender();
void setAge(int _age);
int getAge();
void teach();
private:
string m_strName;
string m_strGender;
int m_iAge;
};
Teacher.cpp
#include<iostream>
#include<string>
#include"Teacher.h"
using namespace std;
void Teacher::setName(string _name)
{
m_strName = _name;
}
string Teacher::getName()
{
return m_strName;
}
void Teacher::setGender(string _gender)
{
m_strGender = _gender;
}
string Teacher::getGender()
{
return m_strGender;
}
void Teacher::setAge(int _age)
{
m_iAge = _age;
}
int Teacher::getAge()
{
return m_iAge;
}
void Teacher::teach()
{
cout << "现在上课..." << endl;
}
3.5 构造函数
3.5.1 对象的初始化
1)有且仅有一次的初始化:
使用构造函数来完成这一过程:
构造函数在对象实例化时被自动调用
构造函数与类同名
构造函数没有返回值
构造函数可以有多个重载形式(也可以给变量默认值,但不可随意去给)
实例化对象时仅用到一个构造函数
当用户没有定义构造函数时,编译器自动生成一个构造函数
/*定义一个Teacher类,具体要求如下:
自定义无参构造函数
自定义有参构造函数
数据成员:
姓名:name
年龄:age
成员函数:
数据成员的封装函数 */
#include<iostream>
#include<string>
#include<stdlib.h>
#include"Teacher.h"
using namespace std;
int main()
{
Teacher t1;
Teacher t2("Mary",55);
cout << t1.getName() << " " << t1.getAge ()<< endl;
cout << t2.getName ()<< " " << t2.getAge() << endl;
system("pause");
return 0;
}
Teacher.h
#include<string>
using namespace std;
class Teacher
{
public:
Teacher();
Teacher(string name, int age);
void setName(string _name);
string getName();
void setAge(int _age);
int getAge();
private:
string m_strName;
int m_iAge;
};
Teacher.cpp
#include<iostream>
#include<string>
#include"Teacher.h"
using namespace std;
Teacher::Teacher()
{
m_strName = "Jim";
m_iAge = 5;
cout << "Teacher()" << endl;
}
Teacher::Teacher(string name, int age)
{
m_strName = name;
m_iAge = age;
cout << "Teacher(string name,int age)" << endl;
}
void Teacher::setName(string _name)
{
m_strName = _name;
}
string Teacher::getName()
{
return m_strName;
}
void Teacher::setAge(int _age)
{
m_iAge = _age;
}
int Teacher::getAge()
{
return m_iAge;
}
2)根据条件的初始化
3.5.2 构造函数的初始化列表
class Student
{
public:
Student()
:m_strName("jim"),m_iAge(10)
{}
private:
string m_strName;
int m_iAge;
};
特性:
初始化列表先于构造函数执行
初始化列表只能用于构造函数
初始化列表可以同时初始化多个数据成员
代码示例:
/* 定义一个Teacher类,具体要求如下:
自定义有参构造函数
使用初始化列表初始化函数
数据成员:
姓名:name
年龄:age
成员函数:
数据成员的封装函数
拓 展:
定义可以带最多学生的个数,此为常量 */
#include<iostream>
#include<string>
#include<stdlib.h>
#include"Teacher.h"
using namespace std;
int main()
{
Teacher t1("Mary",15,150);
cout << t1.getName() << " " << t1.getAge ()<< " "<<t1.getMax()<<endl;
system("pause");
return 0;
}
Teacher.h
#include<iostream>
#include<string>
using namespace std;
class Teacher
{
public:
Teacher(string name ="Jim", int age=15,int m =100);
void setName(string _name);
string getName();
void setAge(int _age);
int getAge();
int getMax();
private:
string m_strName;
int m_iAge;
const int m_iMax;
};
Teacher.cpp
#include<iostream>
#include<string>
#include"Teacher.h"
using namespace std;
Teacher::Teacher(string name, int age, int m) :m_strName(name), m_iAge(age), m_iMax(m)
{
cout << "Teacher(string name,int age)" << endl;
}
void Teacher::setName(string _name)
{
m_strName = _name;
}
string Teacher::getName()
{
return m_strName;
}
void Teacher::setAge(int _age)
{
m_iAge = _age;
}
int Teacher::getAge()
{
return m_iAge;
}
int Teacher::getMax()
{
return m_iMax;
}
3.5.3 拷贝构造函数
定义格式: 类名(const 类名&变量名)
class Student
{
public:
Student(){m_strName = "Jim";}
Student(const Student&stu){}
private:
string m_strName;
};
如果没有自定义的拷贝构造函数则系统自动生成一个默认的拷贝构造函数
当采用直接初始化或复制初始化实例化对象时系统自动调用拷贝构造函数
构造函数内容总结: 构造函数分为: 无参构造函数——默认构造函数
有参构造函数——分参数带默认值,参数不带默认值,2种
系统自动生成的函数: 普通构造函数,拷贝构造函数(二者我们自定义其一,系统就不会生成另一个),而初始化列表均可在构
造函数中使用
代码示例: