学习记录——day40 匿名对象 友元 常成员

一、匿名对象

        没有名字的对象,生命周期只在当前语句内

1、定义格式:直接调用类的构造函数

学习记录——day40 类中特殊的成员函数-CSDN博客

#include <iostream>

using namespace std;

class Stu
{
private:
    string name;
    int age;
    
public:
    Stu(){}//无参构造
    Stu(string n ,int a):name(n),age(a){}//有参构造
    ~Stu(){}//析构函数
    
    void show()
    {
        cout<<name<<" "<<age<<endl;
    }
};

int main()
{
    Stu s1("zzz",18);
    s1.show();
    
    Stu();              //定义匿名对象
    
    return 0;
}

2、匿名对象使用场景

#include <iostream>

using namespace std;

class Stu
{
private:
    string name;
    int age;
    
public:
    Stu(){}//无参构造
    Stu(string n ,int a):name(n),age(a){}//有参构造
    ~Stu(){}//析构函数
    Stu(Stu &other):name(other.name),age(other.age){}//拷贝构造
    Stu(Stu &&other):name(other.name),age(other.age){}//移动构造
    
    void show()
    {
        cout<<name<<" "<<age<<endl;
    }
};

void fun(Stu s)
{
    s.show();
}
int main()
{
    Stu s1("zzz",18);
    s1.show();
    
    Stu();              //定义匿名对象
    
    //匿名对象使用场景1:给新的对象初始化
    Stu s2 = Stu("sss",30);//依赖移动构造
    
    //匿名对象使用场景2:给新的对象组初始化
    Stu s[3] = {Stu("sss",30),Stu("sss",30),Stu("sss",30)};
    
    //匿名对象使用场景3:作为函数的形参传递
    fun(Stu("yyy",500));
    
    return 0;
}

二、友元

        类的封装性较强,对类外的所有数据都屏蔽了信息,类外向访问类内非公共成员需要使用类提供的公共接口。

        如果,在类内将某个外部设置成友元,那么,该友元就会无条件访问该类中的所有权限下的成员。

        由于,友元破坏了内的封装性,使类失去了意义,所以一般不使用

1、友元函数

1)全局函数作为友元函数

#include <iostream>

using namespace std;
class Dog ;
class Cat ;

class Cat
{
private:
    int count;
    int weight;
public:
    Cat(){}
    Cat(int c,int w):count(c),weight(w){}
    friend int sum_count(Cat c,Dog d);
    friend int sum_weight(Cat c,Dog d);
};

class Dog
{
private:
    int count;
    int weight;
public:
    Dog(){}
    Dog(int c,int w):count(c),weight(w){}
    friend int sum_count(Cat c,Dog d);
    friend int sum_weight(Cat c,Dog d);
};

int sum_count(Cat c,Dog d)
{
    return c.count+d.count;
}
int sum_weight(Cat c,Dog d)
{
    return c.weight+d.weight;
}

int main()
{
    Cat c(8,9);
    Dog d(10,5);

    cout<<sum_count(c,d)<<" "<<sum_weight(c,d)<<endl;

    return 0;
}

2)其他类的成员作为友元函数

        声明方法与全局函数一致

        如果类中的某个函数,在其他类中设置成友元,那么该函数必须是类内声明,类外定义

2、友元类

        声明一个A类为B类的友元类,则B允许A访问其所有权限下的成员包括私有成员

        声明格式:friend 类名;

#include <iostream>


using namespace std;
class Stu;                  //对类的前置声明
void  fun(Stu s);
class Teacher;           //将老师类前置声明


//定义老师类
class Teacher
{
private:
    string name;
    string subject;          //课程
public:
    Teacher() {}
    Teacher(string n, string s):name(n), subject(s) {}
    ~Teacher(){}


    //定义成员函数
    void display(Stu s);          //只能类内声明,类外定义


};






class Stu
{
private:
    string name;
    int age;


public:
    Stu() {cout<<"无参构造"<<endl;}          //无参构造
    Stu(string n, int a):name(n),age(a){cout<<"有参构造"<<endl;}    //有参构造
    ~Stu(){cout<<"析构函数"<<endl;}            //析构函数
    Stu(Stu &other):name(other.name), age(other.age){cout<<"拷贝构造"<<endl;}    //拷贝构造
    Stu(Stu &&other):name(other.name), age(other.age){cout<<"移动构造"<<endl;}    //移动构造


    void show()
    {
        cout<<"name = "<<name<<"    age = "<<age<<endl;
    }


    //声明一个全局函数作为友元函数
    friend void  fun(Stu s);


    //声明其他类中的某个成员函数作为友元函数
    //friend void Teacher::display(Stu s);


    //声明老师类为友元类
    friend class Teacher;
};


//将teacher类中国的函数类外定义
void Teacher::display(Stu s)
{
    cout<<"stu::name = "<<s.name<<endl;        //该函数被stu类声明为友元函数
    cout<<"stu::age = "<<s.age<<endl;
}






//定义一个全局函数
void  fun(Stu s)
{
    s.show();           //在类外可以正常调用类中的公共权限下的成员
    cout<<"name = "<<s.name<<endl;       //友元函数可以访问对应类中的所有权限下的成员
    cout<<"age = "<<s.age<<endl;        //友元函数可以访问对应类中的所有权限下的成员
}






int main()
{
    Stu s1("zhangsan", 18);
    fun(s1);


    Teacher t1("zhangpp", "C++");
    t1.display(s1);              //调用成员函数展示其他对象内容




    return 0;
}

3、友元总结

1)不到万不得已的情况下,不要使用友元,因为友元的出现使得封装称为虚谈,友元破坏了类的封装性

2)友元不具有传递性:A是B的朋友,B不一定是A的朋友

3)友元不具有传递性:A是B的朋友,B是C的朋友,A不一定是C的朋友

4)友元不具有继承性:父类的朋友,不一定是子类的朋友

5)必须使用友元的情况:插入和提取运算符重载时,只能使用友元函数来解决

三、常成员    (const)

        对不需要修改的成员进行保护,防止内容被更改

定义格式:定义成员函数时,在括号后加关键字 const

        返回值类型 函数名(形参列表) const

1、常成员函数 

1)定义格式:定义成员函数时,在括号后加关键字 const

返回值类型 函数名(形参列表) const

2)作用:在常成员函数中,是不允许更改成员变量的值

3)类中常成员函数与同名的非 常成员函数构成重载关系,原因是,形参this的类型不同

        非常成员函数中形参this:类名 * const this;

        常成员函数中的形参this: 类名 const * const this;

4)非 常对象,优先调用非常成员函数,如果没有该非常成员函数,那么就会调用同名的常成员函数

2、常对象

1)定义格式:const 类名 对象名;

2)常对象只能调用常成员函数,不能调用非常成员函数

3、mutable 关键字

        使用该关键字修饰的成员变量,可以解除常属性,即使在常成员函数中也能更改该变量的值

#include <iostream>
using namespace std;

class Stu
{
private:
    mutable string name;           //使用mutable修饰的成员变量,运行在常成员函数中被修改
    int age;


public:
    Stu() {cout<<"无参构造"<<endl;}          //无参构造
    Stu(string n, int a):name(n),age(a){cout<<"有参构造"<<endl;}    //有参构造
    ~Stu(){cout<<"析构函数"<<endl;}            //析构函数
    Stu(Stu &other):name(other.name), age(other.age){cout<<"拷贝构造"<<endl;}    //拷贝构造
    Stu(Stu &&other):name(other.name), age(other.age){cout<<"移动构造"<<endl;}    //移动构造


    //定义成员函数
    void show()const        // 类名 const  * const this;
    {
        this->name = "libai";    //在常成员函数中,不能修改成员变量的值,但是可以修改由mutable修饰的成员变量
        //this->age = 100;       //普通的成员变量不能在常成员函数中被修改


        cout<<"name = "<<name<<"    age = "<<age<<endl;
    }


    void show()     // 类名  * const this;
    {
        //name = "libai";    //在常成员函数中,不能修改成员变量的值
        this->age = 100;
        cout<<"name = "<<name<<"    age = "<<age<<endl;
    }


};

int main()
{
    Stu s1("zhangsan", 18);            //定义一个非常对象
    s1.show();                        //非常对象,优先调用非常成员函数


    const Stu s2("lisi", 20);          //定义一个常对象
    s2.show();                        //常对象只能调用常成员函数

    return 0;
}

4、常函数

        保护函数的返回值不被修改

定义格式:const 返回值类型 函数名(形参列表){函数体内容}

#include <iostream>
using namespace std;

//引用函数,const修饰的函数称为常函数
const int &fun()
{
    static int num = 520;
    return num;
}

int main()
{
    cout<<"fun() = "<<fun()<<endl;        //对函数返回值进行读操作


    //fun() = 1314;                //对函数返回值进行写操作,但是const修饰的函数,对函数返回结果进行保护


    cout<<"fun() = "<<fun()<<endl;


    return 0;
}

四、C/C++中const的使用

1、const修饰普通变量,表示定义的是一个常变量,该变量只可读不可写,定义时必须初始化

2、const修饰指针变量时,如果放在*前表示,指针所执行空间中的内容可读不可写

如果放在*后,表示指针的值可读不可写,也就是指针指向不能改变

如果两边都加,表示都不可以更改,都是可读不可写,包含指向和值

3、const修饰函数的形参,表示传过来的数据,可读不可写

4、const修饰函数返回值时,表示保护函数的返回结果不被修改(指针函数和引用函数)

5、const修饰常成员函数,放到成员函数最后面,表示保护成员变量不被修改

  • 29
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值