6-C++远征之封装篇[上]-学习笔记

作者: 天涯明月笙 | 来源:发表于2018-07-21 13:18 被阅读72次

    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;
    }
    
    markmark

    在按下回车的瞬间,可以看到两行输出如下。这是我们t1 t2在销毁时调用析构函数。

    ~Teacher()
    

    堆栈中的对象在销毁时都会自动调用析构函数。

    总结

    梳理前面学过的 & 剧透后面的

    围绕类与对象展开。

    markmark

    类由成员函数和数据成员组成。担心自己的类与其他人重名,类之上可以定义命名空间。

    markmark

    数据成员:

    普通数据成员,(数据类型普通) int, char, char[], string;
    初始化列表(const成员);静态数据成员;对象成员

    markmark

    成员函数:

    对于数据成员进行封装, 属性封装函数(get,set); 一般功能函数;特殊函数:构造函数(根据参数不同,拷贝构造函数-默认构造函数);析构函数.

    markmark

    成员函数 (参数默认值;函数重载;引用;const;)

    对象实例化(堆中实例化,栈中实例化)

    markmark

    对象可以是个引用?对象可以用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;
    }
    

    注意new方式实例化的对象不要忘记delete以及指针置空。

    markmark

    相关文章

      网友评论

        本文标题:6-C++远征之封装篇[上]-学习笔记

        本文链接:https://www.haomeiwen.com/subject/fegapftx.html