【C++】友元、内部类和匿名对象

💗个人主页💗
⭐个人专栏——C++学习
💫点击关注🤩一起学习C语言💯💫

目录

1. 友元

1.1 友元函数

1.2 友元类

2. 内部类

2.1 成员内部类

2.2 局部内部类

3. 匿名对象

3.1 基本概念

3.1 隐式转换


1. 友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以 友元不宜多用。

友元分为:友元函数友元类

1.1 友元函数

友元函数可以访问类的私有成员和受保护成员,即使它们不是类的成员函数。

友元函数在类中声明为友元,可以在类外部定义,但是它们可以访问类的私有和受保护成员。

友元函数的声明方式为将函数声明在类的声明内部,但不是类的成员函数,并使用关键字"friend"来标识它。

在类的外部定义友元函数时,不需要使用类名限定,直接定义即可。

class MyClass 
{
private:
    int num;
public:
    MyClass(int n) 
        : num(n) 
    {}
    friend void printNum(const MyClass& obj);
};

void printNum(const MyClass& obj) 
{
    cout << "Num: " << obj.num << endl;  // 可以访问类的私有成员num
}

int main() 
{
    MyClass obj(10);
    printNum(obj);  // 调用友元函数
    return 0;
}

友元函数的使用场景包括:

  1. 当某个函数需要访问类的私有成员时,可以将该函数声明为类的友元函数。
  2. 当需要重载运算符时,可以将重载函数声明为类的友元函数。
  3. 当需要在类的各个对象之间进行相互操作或访问私有数据时,可以使用友元函数。

友元函数的一个重要限制是,在类的声明内部声明为友元函数的函数需要在类之外定义。因此,友元函数不能直接访问类的成员变量和成员函数,需要使用对象的引用或指针来访问。

1.2 友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

  • 友元关系是单向的,不具有交换性。
  • 友元关系不能传递 如果C是B的友元, B是A的友元,则不能说明C时A的友元。
  • 友元关系不能继承,在继承位置再给大家详细介绍。
class ClassA 
{
private:
    int numA;
protected:
    int numB;
public:
    ClassA(int a, int b) 
        : numA(a), 
        numB(b) 
    {}
    friend class ClassB;
};

class ClassB 
{
public:
    void printNum(const ClassA& obj) 
    {
        cout << "NumA: " << obj.numA << endl;  // 可以访问类A的私有成员numA
        cout << "NumB: " << obj.numB << endl;  // 可以访问类A的受保护成员numB
    }
};

int main() 
{
    ClassA objA(10, 20);
    ClassB objB;
    objB.printNum(objA);  // 调用友元类的成员函数
    return 0;
}

友元类的使用场景包括:

  1. 当一个类需要访问另一个类的私有成员时,可以将该类声明为友元类。
  2. 当需要在类之间进行相互操作或访问私有数据时,可以使用友元类。

2. 内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类, 它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越 的访问权限。

注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访 问外部类中的所有成员。但是外部类不是内部类的友元。

内部类可以分为两种类型:成员内部类和局部内部类。

特性:

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
  3. sizeof(外部类)=外部类,和内部类没有任何关系。

2.1 成员内部类

成员内部类是在外部类的内部定义的一个类,它可以访问外部类的所有成员,包括私有成员。

成员内部类的定义通常放在外部类的声明中,但是它的实现需要在外部类的作用域之外进行。

class OuterClass
{
private:
    int _x;
    static int y;
public:
    OuterClass(int x = 10)
        :_x(x)
    {}
    class InnerClass
    {
    public:
        void display(OuterClass obj)
        {
            cout << "x = " << obj._x << endl;
            cout << "y = " << y << endl;
        }
    };
};

int OuterClass::y = 0; // 静态成员变量初始化

int main() {
    OuterClass obj1;
    OuterClass::InnerClass obj2;

    obj2.display(obj1);

    return 0;
}

2.2 局部内部类

局部内部类是在函数或代码块内定义的一个类,它只在该函数或代码块的作用域内可见。

局部内部类可以访问外部类的所有成员,包括私有成员。

void outerMethod() 
{
    class LocalClass 
    {
    public:
        void display() 
        {
            cout << "This is a local inner class" << endl;
        }
    };
    LocalClass obj;
    obj.display();
}

int main() 
{
    outerMethod();
    return 0;
}

3. 匿名对象

3.1 基本概念

匿名对象是指在创建对象时,没有为对象指定一个具体的名称,而是直接使用对象执行操作或调用方法。匿名对象在使用后就被销毁,无法再次引用。

class MyClass 
{
public:
    void display() 
    {
        cout << "This is a MyClass object" << endl;
    }
};

int main() 
{
    // 创建一个匿名对象并调用其display()方法
    MyClass().display();

    return 0;
}

3.1 隐式转换

C++中的匿名对象可以进行隐式转换。

隐式转换是指在某些情况下,编译器会自动将一个对象转换为目标类型,而无需显式地使用类型转换操作符。

1. 赋值操作:可以将匿名对象直接赋值给另一个对象。​​​​​​​​​​​​​​

class MyClass
{
public:
    MyClass(int value) 
        : m_value(value) 
    {}
    int getValue() 
    { 
        return m_value; 
    }
private:
    int m_value;
};

int main() {
    MyClass obj = MyClass(10); // 匿名对象被隐式转换并赋值给obj
    cout << obj.getValue(); // 输出:10
    return 0;
}

2. 函数返回值:一个函数可以返回一个匿名对象,并且该匿名对象会被隐式转换为函数返回类型。

class MyClass 
{
public:
    MyClass(int value) 
        : m_value(value) 
    {}
    int getValue() 
    { 
        return m_value; 
    }
private:
    int m_value;
};

MyClass createObject() 
{
    return MyClass(10); // 返回一个匿名对象
}

int main() 
{
    MyClass obj = createObject(); // 匿名对象被隐式转换并赋值给obj
    cout << obj.getValue(); // 输出:10
    return 0;
}

3. 表达式中的运算:在一些表达式中,匿名对象可以参与运算,并且会被隐式转换为相应的类型。

class MyClass 
{
public:
    MyClass(int value) 
        : m_value(value) 
    {}
    int getValue() 
    { 
        return m_value; 
    }
    MyClass operator +(const MyClass& other) 
    {
        return MyClass(m_value + other.m_value); // 返回一个匿名对象
    }
private:
    int m_value;
};

int main() 
{
    MyClass obj1(10);
    MyClass obj2(20);
    MyClass result = obj1 + obj2; // 匿名对象参与运算并被隐式转换为MyClass
    cout << result.getValue(); // 输出:30
    return 0;
}

python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明),含有代码注释,新手也可看懂,个人手打98分项目,导师非常认可的高分项目,毕业设计、期末大作业和课程设计高分必看,下载下来,简单部署,就可以使用。该项目可以直接作为毕设、期末大作业使用,代码都在里面,系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值,项目都经过严格调试,确保可以运行! python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实现mysql数据库(源码+文档说明)python基于django框架仓库管理系统设计与实
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流浪者与猴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值