C++ 类和对象(成员,this指针,友元,运算符重载)

1. 初始化列表:

                   作用:提供初始化列表语法,用于初始化属性

                   语法:构造函数() : 属性1(值1),属性2(值2),属性3(值3)

2. 类对象作为类成员

                    C++类中的成员可以时另一个类的对象,该成员为对象成员。

                    注:当其他类对象作为本类成员,构造时先构造类对象,再构造自身,析构顺序与构造相反 

            C++编译器至少给一个类添加四个函数:

                      ① 默认构造函数(无参,函数体为空)

                      ② 默认析构函数(无参,函数体为空)

                      ③ 默认拷贝函数,对属性进行值拷贝

                      ④ 赋值运算符 operator= ,对属性进行值拷贝

3. 静态成员

                     静态成员是在成员变量和成员函数前加上关键字static ,称为静态成员

                     静态成员变量:

                               ① 所有对象共享用一份数据

                               ② 在编译阶段分配内存

                               ③ 类内声明,类外初始化 

                     静态成员函数:

                                 ① 所有对象共享一个函数

                                 ② 静态成员函数只能访问静态成员变量

class Test()
{
public:
    //初始化列表初始化属性
    Test(int a,int b,int c):m_a(a),m_b(b),m_c(c)
    {
    }

    static void func()
    {
        //静态成员函数只能访问 静态变量
        m_sA = 10086;
        //m_c = 666;  //无法访问
        cout << "静态函数调用" << endl;
    }
private:
    int m_a;
    int m_b;
    int m_c;
    
    //静态成员变量
    static int m_sA;
}

//静态成员变量,类内声明,类外初始化
int Test::m_sA = 200;

class RunTest()
{
public:
    RunTest(){
         //1.通过对象访问
         Test t;
         t.func(); 

         //2.通过类名访问
         Test::func();
    }
    ~RunTest(){}
private:
    //注:当其他类对象作为本类成员,构造时先构造类对象,再构造自身,析构顺序与构造相反 
   Test m_test;
};


int main()
{
    RunTest t();

    system("puase");
    return 0;
}

4. 对象模型和this指针

         成员变量和成员函数分开储存,只有非静态成员变量才属于类的对象上

                 C++编译器会给每个空对象也分配一个字节空间,为了区分空对象占内存位置

         this指针概念

                  C++通过提供特殊的对象指针,this指针,区分对象调用自己。this指针指被调用的成员函数所属的对象

                   this指针是隐含每一个非静态成员函数内的一种指针,不需要定义,直接使用即可。

                   作用

                          ① 当形参和成员变量同名时,可用this指针区分

                          ② 在类的非静态成员函数中返回对象本身,可使用 return *this;

            空指针访问成员函数 

                       C++中空指针也是可以调用成员函数的,但要注意有无用到this指针

             const 修饰成员函数

                          常函数:

                                 成员函数后加const后,称这个函数为常函数

                                 常函数类不可以修改成员属性

                                 成员属性声明时加关键字mutable后,在常函数中依然可以修改

                           常对象

                                  声明对象前加const,称该对象为常对象

                                  常对象只能调用常函数

class Person()
{
public:
    Person(int num)
    {
        this.m_A = num;
    }

    //返回引用
    Person& addNum(int num)
    {
         m_A += num;
         return *this;
    }

    //返回新对象,调用拷贝函数
    Person add(int num)
    {
         m_A += num;
         return *this;
    }

    //指针本质时指针常量,指针指向是不可修改的
    //const Person *const this;
    //在成员函数后加const,修饰的是this指向
    void show() const
    {
        //this->m_A = 100;  //编译错误
        //this = NULL //this指针不可修改指针的指向
        this->m_C = 100;
    }    

    int m_A;         //非静态成员变量,属于类的对象上
    
    void func(){}    //非静态成员函数,不属于类的对象上

    static int m_B;    //静态成员变量,不属于类的对象上
    static void func1(){}  //静态成员函数,不属于类的对象上
    
    mutable int m_C;    //加关键字:mutable 常函数内仍可修改
};
int Person::m_B = 100;

int main()
{
    //链式编程思想
    Person p1(10);
    Person p2(10);
    p1.add(10).add(10).add(10);            //返回引用,得出 40
    p2.addNum(10).addNum(10).addNum(10);   //返回值,得出 20

    const Person p;
    //p.m_A = 100;    //编译报错
    p.m_C = 100;

    //常对象只能调用常函数
    //p.add(10);    //常函数 不可以调用普通成员函数,因为普通成员函数可以修改属性
    p.show();
    

    system("puase");
    return 0;
}

5.友元

友元 目的是让函数或者类 访问另一个类中的私有成员。

关键字:friend

友元三种实现:

       ① 全局函数做友元

       ② 类做友元

       ③ 成员函数做友元


class FriendCl;
class Building
{
    //goodGay全局函数 友元,可以访问 私有成员
    friend void goodGay(const Building & building);
    
    //FriendCl是友元类,可以访问 私有成员
    //friend class FriendCl;

    //visit是FriendCl类的友函数,可以访问 私有成员
    friend  void FriendCl::visit();
public:
    Building();
public:
     string m_sittingRoom;    //客厅

private:
     string m_bedRoom;        //卧室

};

Building::Building()
{
    m_sittingRoom = "客厅";
    m_bedRoom= "卧室";
}

//① 全局函数  友元
void goodGay(const Building & building)
{
    cout << "全局函数  访问公有成员:"<<building.m_sittingRoom << endl;
    cout << "全局函数  访问私有成员:"<<building.m_bedRoom<< endl;
}

//② 类 友元
class FriendCl
{
public:
    FriendCl();
    void visit();  
    Building *m_building;
}

FriendCl::FriendCl()
{
    m_building = new Building();
}
void FriendCl::visit()
{
    cout << "友元类  访问公有成员:"<<building.m_sittingRoom << endl;
    cout << "友元类  访问私有成员:"<<building.m_bedRoom<< endl;
}

int main()
{
    //全局函数友元测试
    Building build;
    goodGay(build);
    
    //友元类/友元函数 测试
    FriendCl f;
    f.visit();
    
    system("pause");
    return 0;
}


6.运算符重载

概念:对已有运算符重新进行定义,赋予其另外一种功能,以适应不同数据类型

对内置的数据类型的表达式的运算符是不可能改变的;不要乱用运算符重载

(+加法运算符重载,<< 左移运算符重载,++递增运算符重载,=赋值运算符重载,

<、>、==、!= 关系运算符重载,()函数调用运算符重载)

class NumClass()
{
    friend ostream & opearator<<(ostream &cout ,NumClass &c)
public:
    NumClass(){}
    NumClass(const int num):m_num(num){}
    NumClass(const int a,const int b):m_a(a),m_b(b){}
    ~NumClass()
    {
        if(m_age != NULL)
        {
            delete m_age;
            m_age = NULL;
        }
    }

    //成员函数重载 +号
    NumClass opearator+(NumClass &c)
    {
        NumClass tmp;
        tmp.m_a = this->m_a + c.m_a;
        tmp.m_b = this->m_b + c.m_b;
        return tmp;
    }
    //运算符重载 也可以发生函数重载
    NumClass opearator+(int &num)
    {
         NumClass tmp;
         tmp.m_a = this->m_a + num;
         tmp.m_b = this->m_b + num;
         return tmp;
    }
    /
    //重载前置++ 运算符(返回引用,为了一直对同一数据做递增操作)
    NumClass& operator++()
    {
        m_num++;
        return *this;
    }
    //重载后置++ 运算符(返回值,int为占位参数,可以用于区分前置和后置)
    NumClass operator++(int)
    {
        NumClass tmp = *this;    //先记录结果
        m_num++;                 //后递增操作
        return tmp;              //返回记录结果
    }
    /
    //重载 赋值运算符
    NumClass& operator=(NumClass &c)
    {
        //编译器是提供浅拷贝
        //m_age = c.m_age;
    
        //应先判断是否属性在堆区,如果友先释放,后深拷贝
        if(m_age != NULL)
        {
             delete m_age;
             m_age = NULL;
        }
        m_age = new int(*c.m_age); 
        return *this;
    }
    
    //重载 关系运算符
    bool operator==(NumClass &c)
    {
        returm (m_a == c.m_a &&
                m_b == c.m_a &&
                m_num == c.m_num);
    }
    //重载 函数调用运算符 (仿函数)
    void operator()(string text)
    {
        cout << text();
    } 


    int m_a;
    int m_b;
    int m_num;
    int *m_age;
};

//全局函数重载 +号
NumClass opearator+(NumClass &c1,NumClass &c2)
{
     NumClass tmp;
     tmp.m_a = c1->m_a + c2.m_a;
     tmp.m_b = c1->m_b + c2.m_b;
     return tmp;
}

//全局函数重载 << 左移运算符
ostream & opearator<<(ostream &cout ,NumClass &c)
{
    cout << "m_a:" << c.m_a << " m_b:" << c.m_a;
    return cout;
}


int main()
{
    NumClass n1(10,20);
    NumClass n2(20,40);
    
    //成员函数重载 本质调用
    //NumClass n3 = n1.opearator+(n2);
    //全局函数重载 本质调用
    //NumClass n3 = opearator+(n1,n2);

     NumClass n3 = n1+n2;
    cout << "n3:m_a:" << n3.m_a << endl;    //得30
    cout << "n3:m_b:" << n3.m_b << endl;    //得60

    //运算符重载 也可以发生函数重载
    NumClass n4 = n1+30;
    cout << "n4:m_a:" << n4.m_a << endl;    //得40
    cout << "n4:m_a:" << n4.m_a << endl;    //得50

    //重载输出运算符
    cout << "n4:" <<  n4 << endl;

    //操作递增运算符
    NumClass n5(100);
    cout << "n5:" <<  ++n4 << endl;    //得101
    cout << "n5:" <<  n4++ << endl;    //得100
    cout << "n5:" <<  n4 << endl;      //得101

    //函数调用运算符重载
    NumClass myClass;
    myClass("Hello word");
    //匿名函数对象
    NumClass()("test");

    system("pause");
    return 0;
}

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页