C++远征之封装篇(上)
课程简介
- 类(抽象概念),对象(真实具体)
- 配角: 数据成员和成员函数(构成了精彩而完整的类)
- 构造函数 & 析构函数(描述了对象的生生死死)
- 对象复制和对象赋值 (使类的定义充满艺术)
- 对象数组和对象指针 (将应用型态发挥到淋漓尽致)
- this指针(影子,贯穿大戏始终,却很少崭露头角)
大家的思维模式会从面向过程到面向对象。处理更复杂程序。
学完之后,搞一个迷宫的寻路程序。
类和对象
- 类(概念,从对象中抽象出的)和对象(具体的事物)
人类忠实的朋友:
c++类定义数据成员(属性)、成员函数(方法)
思考: 抽象出来的是否是狗的全部信息
非法字符串link结论:目的不同抽象出的信息不同,我们只抽象出我们自己需要的信息。
纯字符串连接为非法操作。只有纯字符串和string,以及string与string是合法的。
代码演示
题目因为要判定输入是不是为空。所以不能简单的使用cin而应该使用getline
3-1-NameStringDemo/main.cpp
#include <stdlib.h>
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string name;
cout << "please input your name:";
getline(cin, name);
if (name.empty()){
cout << "input is null" << endl;
system("pause");
return 0;
}
if (name == "mtianyan")
{
cout << "you are a admin" << endl;
}
cout << "hello ," + name << endl;
cout << "your name length is :" << name.size() << endl;
cout << "your name frist letter is :" << name[0] << endl;
system("pause");
return 0;
}
c++中通过
getline
获取外界控制台输入(当包含可能输入为空情况)。一般情况还是cin好了。
管理员:
同文件类外定义为了标识这是属于汽车car的成员函数:car::
同文件类外定义是突击队的话,分文件类外定义就是正规军了。
几乎所有的c++程序,专业点的程序员都会分文件类外定义。
分文件类外定义
分文件类外定义一个.h头文件,名称与类名一致。必须包含.h文件,并使用
car::
类外定义代码演示
要求:
题目要求5-2-1-OutClassDefine1/main.cpp
#include <stdlib.h>
#include <iostream>
#include <string>
using namespace std;
class Teacher {
public:
void setName(string name);
string getName();
void setGender(std::string val);
string getGender();
void setAge(int _age);
int getAge();
void teach();
private:
string m_strName;
string m_strGender;
int m_iAge;
};
string Teacher::getName()
{
return m_strName;
}
void Teacher::setName(string name)
{
m_strName = name;
}
string Teacher::getGender()
{
return m_strGender;
}
void Teacher::setGender(string val)
{
m_strGender = val;
}
int Teacher::getAge() {
return m_iAge;
}
void Teacher::setAge(int _age) {
m_iAge = _age;
}
void Teacher::teach() {
cout << "现在上课" << endl;
};
int main(void)
{
Teacher teacher;
teacher.setAge(21);
teacher.setName("mtianyan");
teacher.setGender("男");
cout << teacher.getName() << " " << teacher.getGender() << " " << teacher.getAge() << endl;
teacher.teach();
system("pause");
return 0;
}
类实例化内存
对象初始化
要求 Teacher();
Teacher(string name, int age=20);
这样的计算机是可以分辨的,但是如果给name也给默认值。那么将无法通过编译。
提示重载函数的调用不明确。两个不能共存,但是可以单独存在。
6-2-ConstructorFunction
Teacher.h
#include <string>
using namespace std;
class Teacher {
public:
Teacher();
Teacher(string name, int age=20);
void setName(string name);
string getName();
void setAge(int _age);
int getAge();
void teach();
private:
string m_strName;
int m_iAge;
};
teacher.cpp
#include "Teacher.h"
#include <iostream>
#include <string>
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;
}
string Teacher::getName()
{
return m_strName;
}
void Teacher::setName(string name)
{
m_strName = name;
}
int Teacher::getAge() {
return m_iAge;
}
void Teacher::setAge(int _age) {
m_iAge = _age;
}
void Teacher::teach() {
cout << "现在上课" << endl;
};
main.cpp
#include <iostream>
#include <string>
#include "Teacher.h"
using namespace std;
int main(void)
{
Teacher teacher; //无参数实例化,这里能正常运行是因为我们没有给参数都加默认值。
Teacher t2("merry", 15);//有参数实例化
Teacher t3("james");//,构造函数有默认值20
cout << teacher.getName() << " " << teacher.getAge() << endl;
cout << t2.getName() << " " << t2.getAge() << endl;
cout << t3.getName() << " " << t3.getAge() << endl;
teacher.teach();
system("pause");
return 0;
}
要求
定义有参默认构造函数,使用初始化列表初始化数据。
6-5-ParameterConstructorFunctionInitList
Teacher.h
#include <string>
using namespace std;
class Teacher {
public:
Teacher(string name ="hi", int age=1,int m =100); // 有参默认构造函数
void setName(string name);
string getName();
void setAge(int _age);
int getAge();
int getMax();
void setMax(int m_iMax);
private:
string m_strName;
int m_iAge;
const int m_iMax;
};
Teacher.cpp
#include "Teacher.h"
#include <iostream>
#include <string>
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;
}
string Teacher::getName()
{
return m_strName;
}
void Teacher::setName(string name)
{
m_strName = name;
}
int Teacher::getAge() {
return m_iAge;
}
void Teacher::setAge(int _age) {
m_iAge = _age;
}
int Teacher::getMax() {
return m_iMax;
}
void Teacher::setMax(int m_iMax) {
m_iMax = m_iMax;
}
main.cpp
#include <stdlib.h>
#include <iostream>
#include <string>
#include "Teacher.h"
using namespace std;
int main(void)
{
Teacher teacher("merry",12,150);
cout << teacher.getName() << " " << teacher.getAge() <<" "<<teacher.getMax()<< endl;
system("pause");
return 0;
}
要求
6-8-CopyConstructorFunction
Teacher.h
#include <string>
using namespace std;
class Teacher {
public:
Teacher(string name ="mtianyan", int age=21,int m =100);
Teacher(const Teacher& tea); //拷贝构造函数
void setName(string name);
string getName();
void setAge(int _age);
int getAge();
private:
string m_strName;
int m_iAge;
};
teacher.cpp
#include "Teacher.h"
#include <iostream>
#include <string>
using namespace std;
Teacher::Teacher(string name, int age ,int m):m_strName(name),m_iAge(age)
{
cout << "Teacher(string name, int age)" << endl;
}
Teacher::Teacher(const Teacher& tea) {
cout << "Teacher(const Teacher &tea)" << endl;
}
string Teacher::getName()
{
return m_strName;
}
void Teacher::setName(string name)
{
m_strName = name;
}
int Teacher::getAge() {
return m_iAge;
}
void Teacher::setAge(int _age) {
m_iAge = _age;
}
main.cpp
#include <stdlib.h>
#include <iostream>
#include <string>
#include "Teacher.h"
using namespace std;
void test(Teacher t) {
}
int main(void)
{
Teacher teacher;
Teacher t2 = teacher;
Teacher t3(t2); // 这里无论使用t2还是teacher都只会调用拷贝构造函数
test(teacher); //函数使用已实例化的对象时调用。
cout << teacher.getName() << " " << teacher.getAge() << endl;
system("pause");
return 0;
}
要求
按回车后一瞬间可以看到析构函数被调用
6-11-DestructorFunction
Teacher.h
#include <string>
using namespace std;
class Teacher {
public:
Teacher(string name ="mtianyan", int age=21,int m =100); // 构造
Teacher(const Teacher &tea); // 拷贝构造
~Teacher(); // 析构
void setName(string name);
string getName();
void setAge(int _age);
int getAge();
private:
string m_strName;
int m_iAge;
};
Teacher.cpp
#include "Teacher.h"
#include <iostream>
#include <string>
using namespace std;
Teacher::Teacher(string name, int age ,int m):m_strName(name),m_iAge(age)
{
cout << "Teacher(string name, int age)" << endl;
}
Teacher::Teacher(const Teacher &tea) {
cout << "Teacher(const Teacher &tea)" << endl;
}
Teacher::~Teacher() {
cout << "~Teacher()" << endl;
}
string Teacher::getName()
{
return m_strName;
}
void Teacher::setName(string name)
{
m_strName = name;
}
int Teacher::getAge() {
return m_iAge;
}
void Teacher::setAge(int _age) {
m_iAge = _age;
}
main.cpp
#include <stdlib.h>
#include <iostream>
#include <string>
#include "Teacher.h"
using namespace std;
void test(Teacher t) {
}
int main(void)
{
Teacher t1;
Teacher t2(t1);
Teacher *p = new Teacher();
delete p;
p = NULL;
system("pause");
return 0;
}
mark
在按下回车的瞬间,可以看到两行输出如下。这是我们t1 t2在销毁时调用析构函数。
~Teacher()
堆栈中的对象在销毁时都会自动调用析构函数。
总结
梳理前面学过的 & 剧透后面的
围绕类与对象展开。
mark类由成员函数和数据成员组成。担心自己的类与其他人重名,类之上可以定义命名空间。
mark数据成员:
mark普通数据成员,(数据类型普通) int, char, char[], string;
初始化列表(const成员);静态数据成员;对象成员
成员函数:
mark对于数据成员进行封装, 属性封装函数(get,set); 一般功能函数;特殊函数:构造函数(根据参数不同,拷贝构造函数-默认构造函数);析构函数.
成员函数 (参数默认值;函数重载;引用;const;)
对象实例化(堆中实例化,栈中实例化)
mark对象可以是个引用?对象可以用const修饰么?
- 成员函数中如何辨识数据成员。
- 多个对象如何共享数据
- 对象成员初始化
综合练习:
定义一个Student类,包含名字一个数据成员,定义无参构造函数、有参构造函数、拷贝构造函数、析构函数及对于名字的封装函数,在main函数中实例化Student对象,并访问相关函数,观察运行结果。
7-2-StudentDemo/main.cpp
#include <stdlib.h>
#include <iostream>
#include <string>
using namespace std;
/**
* 定义类:Student
* 数据成员:m_strName
* 无参构造函数:Student()
* 有参构造函数:Student(string _name)
* 拷贝构造函数:Student(const Student& stu)
* 析构函数:~Student()
* 数据成员函数:setName(string _name)、getName()
*/
class Student {
public:
Student() {
m_strName = "";
};
Student(string _name) {
m_strName = _name;
};
Student(const Student& stu) {
};
~Student() {
};
void setName(string _name) {
m_strName = _name;
};
string getName() {
return m_strName;
};
private:
string m_strName;
};
int main(void)
{
// 通过new方式实例化对象*stu
Student *stu = new Student();
// 更改对象的数据成员为“mtianyan”
stu->setName("mtianyan");
// 打印对象的数据成员
cout << stu->getName() << endl;
delete stu;
stu = NULL;
system("pause");
return 0;
}
mark注意new方式实例化的对象不要忘记delete以及指针置空。
网友评论