类与对象(下)

前言:

在 C++ 面向对象编程中,类与对象是代码组织的核心,但想要真正驾驭它,需要深入理解那些"藏在背后"的进阶特性。从再探构造函数的细节,到对象拷贝时的编译优化,每一个知识点都能让你写出更高效、更优雅的代码。

一、再探构造函数:不止是"初始化"

构造函数是创建对象时自动调用的特殊函数,但它的作用远不止给成员变量赋值:

  • 默认构造函数:如果没有显式定义任何构造函数,编译器会自动生成一个空的默认构造函数;但如果定义了带参数的构造函数,默认构造函数会"消失",需要手动声明。

  • 拷贝构造函数:用一个已存在的对象初始化新对象时调用,默认的拷贝构造函数会做"浅拷贝"------只复制成员变量的值,对于指针等资源会导致"双重释放"问题,需要手动实现"深拷贝"。

  • 移动构造函数(C++11+):当对象是"临时值"(如函数返回的局部对象)时,移动构造函数会"接管"原对象的资源,避免不必要的拷贝,大幅提升效率。

二、类型转换:让对象"灵活变身"

C++ 允许类之间的隐式或显式类型转换,主要通过两种方式实现:

  • 构造函数转换:如果一个构造函数只接受一个参数(或除第一个参数外其他参数都有默认值),它可以将该类型的值隐式转换为类对象。

  • 类型转换函数:在类中定义一个无参数、无返回值声明(但需要返回目标类型)的函数,格式为 operator 目标类型() ,用于将类对象转换为其他类型。

示例:类型转换函数

复制代码
class MyInt {
private:
    int value;
public:
    MyInt(int v) : value(v) {}
    // 转换为 int 类型
    operator int() const {
        return value;
    }
};

int main() {
    MyInt a(10);
    int b = a; // 自动调用 operator int()
    cout << b << endl; // 输出 10
    return 0;
}

三、static 成员:属于类的"共享资源"

static 关键字可以修饰类的成员变量和成员函数:

  • static 成员变量:不属于任何对象,而是属于整个类,所有对象共享同一份值;需要在类外单独初始化,格式为 类型 类名::成员变量名 = 初始值 。

  • static 成员函数:没有 this 指针,只能访问 static 成员变量和其他 static 成员函数,不能访问非 static 成员;可以通过类名直接调用,无需创建对象。

    class Counter {
    private:
    static int count; // 声明 static 成员变量
    public:
    Counter() { count++; }
    static int getCount() { // static 成员函数
    return count;
    }
    };

    int Counter::count = 0; // 初始化 static 成员变量

    int main() {
    Counter a, b, c;
    cout << Counter::getCount() << endl; // 输出 3
    return 0;
    }

四、友元:打破封装的"特殊通道"

五、内部类:类里的"小类"

在一个类的内部定义另一个类,称为内部类(也叫嵌套类):

  • 内部类是一个独立的类,不属于外部类的成员,只是作用域被限制在外部类中;

  • 内部类可以直接访问外部类的 static 成员,但不能直接访问外部类的非 static 成员,需要通过外部类的对象来访问;

  • 外部类不能直接访问内部类的成员,需要创建内部类的对象。

示例:内部类的定义

复制代码
class Outer {
private:
    int outerValue = 10;
public:
    class Inner { // 内部类
    public:
        void showOuter(Outer& o) {
            cout << o.outerValue << endl; // 访问外部类的非 static 成员
        }
    };
};

int main() {
    Outer o;
    Outer::Inner i;
    i.showOuter(o); // 输出 10
    return 0;
}

六、匿名对象:"即用即弃"的临时对象

匿名对象是没有名字的对象,通常用于临时调用成员函数或作为函数参数:

  • 匿名对象的生命周期只在当前行,执行完当前行后会被销毁;

  • 可以简化代码,避免创建不必要的命名对象。

示例:匿名对象的使用

复制代码
class Printer {
public:
    void print(const char* str) {
        cout << str << endl;
    }
};

int main() {
    Printer().print("Hello, Anonymous!"); // 匿名对象调用成员函数
    return 0;
}
相关推荐
程序员水自流2 小时前
【AI大模型第9集】Function Calling,让AI大模型连接外部世界
java·人工智能·llm
‿hhh2 小时前
综合交通运行协调与应急指挥平台项目说明
java·ajax·npm·json·需求分析·个人开发·规格说明书
小徐Chao努力2 小时前
【Langchain4j-Java AI开发】06-工具与函数调用
java·人工智能·python
无心水2 小时前
【神经风格迁移:全链路压测】33、全链路监控与性能优化最佳实践:Java+Python+AI系统稳定性保障的终极武器
java·python·性能优化
萧曵 丶2 小时前
Synchronized 详解及 JDK 版本优化
java·多线程·synchronized
夏幻灵2 小时前
JAVA基础:基本数据类型和引用数据类型
java·开发语言
weixin199701080162 小时前
闲鱼 item_get - 商品详情接口对接全攻略:从入门到精通
java·后端·spring
cike_y3 小时前
Spring-Bean的作用域&Bean的自动装配
java·开发语言·数据库·spring
qq_12498707533 小时前
基于深度学习的蘑菇种类识别系统的设计与实现(源码+论文+部署+安装)
java·大数据·人工智能·深度学习·cnn·cnn算法