再识C++面向对象

本文详细探讨了C++中的构造函数,包括构造函数体赋值、初始化列表和explicit关键字,以及静态成员的特性。此外,还介绍了友元函数和友元类的概念,内部类的访问权限,匿名对象的使用,以及拷贝对象时的编译器优化如复制消除和移动语义。最后,强调了封装在面向对象编程中的重要性。
摘要由CSDN通过智能技术生成

构造函数、静态成员、友元、内部类、匿名对象以及拷贝对象时的编译器优化,这些是面向对象编程中重要的概念和特性。本文将详细探讨每个主题,并结合代码示例加深理解。

1. 再谈构造函数

构造函数是在创建对象时自动调用的特殊成员函数,用于初始化对象的数据成员。在C++中,构造函数的名称与类名相同,没有返回类型,可以有参数,也可以没有参数。构造函数有以下几种常见的形式:

1.1 构造函数体赋值

构造函数体赋值是一种构造函数的定义形式,它可以在构造函数体内给对象的成员变量赋初值。这种方式适用于简单的成员初始化。

#include <iostream>
using namespace std;

class Point {
public:
    // 构造函数体赋值
    Point(int x = 0, int y = 0) {
        this->x = x;
        this->y = y;
    }

    void print() {
        cout << "x: " << x << ", y: " << y << endl;
    }

private:
    int x;
    int y;
};

int main() {
    Point p1;           // 调用 Point::Point(int x = 0, int y = 0)
    Point p2(1, 2);     // 调用 Point::Point(int x, int y)
    p1.print();         // 输出: x: 0, y: 0
    p2.print();         // 输出: x: 1, y: 2

    return 0;
}

1.2 初始化列表

初始化列表是构造函数的另一种定义形式,它在构造函数的参数列表后面使用冒号初始化成员变量,可以提高初始化效率并用于初始化const成员和引用成员。

#include <iostream>
using namespace std;

class Point {
public:
    // 初始化列表
    Point(int x = 0, int y = 0) : x(x), y(y) {}

    void print() {
        cout << "x: " << x << ", y: " << y << endl;
    }

private:
    int x;
    int y;
};

int main() {
    Point p1;           // 调用 Point::Point(int x = 0, int y = 0)
    Point p2(1, 2);     // 调用 Point::Point(int x, int y)
    p1.print();         // 输出: x: 0, y: 0
    p2.print();         // 输出: x: 1, y: 2

    return 0;
}

1.3 explicit关键字

有时候,构造函数可以被用于类型转换,为了防止意外的隐式类型转换,可以在构造函数前加上`explicit`关键字。这样的构造函数只能用于显式地创建对象,而不能进行隐式类型转换。

#include <iostream>
using namespace std;

class Celsius {
public:
    explicit Celsius(float temp) : temperature(temp) {}

    void print() {
        cout << "Temperature in Celsius: " << temperature << " C" << endl;
    }

private:
    float temperature;
};

void showTemperature(Celsius c) {
    c.print();
}

int main() {
    Celsius c1(25.0);
    c1.print();         // 输出: Temperature in Celsius: 25 C

    // 编译错误,无法隐式进行类型转换
    // showTemperature(25.0);

    // 必须显式地创建对象
    showTemperature(Celsius(25.0)); // 输出: Temperature in Celsius: 25 C

    return 0;
}

2. Static成员

2.1 概念

在C++中,静态成员是类的成员,不属于类的任何对象,而是属于整个类,它在所有对象之间共享。静态成员包括静态数据成员和静态成员函数。

2.2 特性

静态成员有以下特性:

- 静态数据成员在程序运行期间只有一份拷贝,被所有对象共享。
- 静态数据成员必须在类外初始化,并且不能在类内进行初始化。
- 静态成员函数只能访问静态数据成员和其他静态成员函数,不能访问非静态数据成员和非静态成员函数。

#include <iostream>
using namespace std;

class Counter {
public:
    static int count; // 静态数据成员声明
    int num;

    Counter() {
        count++;
        num = count;
    }

    static void showCount() { // 静态成员函数
        cout << "Count: " << count << endl;
    }
};

int Counter::count = 0; // 静态数据成员定义和初始化

int main() {
    Counter c1, c2, c3;
    Counter::showCount(); // 输出: Count: 3

    return 0;
}

3. 友元

3.1 友元函数

在C++中,友元函数是在类外部声明的普通函数,它可以访问类的私有成员和保护成员。通过使用`friend`关键字,可以将一个函数声明为友元函数。

#include <iostream>
using namespace std;

class Point {
public:
    Point(int x, int y) : x(x), y(y) {}

    friend void showPoint(Point p); // 声明友元函数

private:
    int x;
    int y;
};

void showPoint(Point p) { // 定义友元函数
    cout << "Point: (" << p.x << ", " << p.y << ")" << endl;
}

int main() {
    Point p(3, 4);
    showPoint(p); // 输出: Point: (3, 4)

    return 0;
}

3.2 友元类

除了友元函数,C++还支持友元类的概念。友元类可以访问其所在类的私有成员和保护成员。

通过使用`friend`关键字,将一个类声明为另一个类的友元类。

#include <iostream>
using namespace std;

class Point {
public:
    Point(int x, int y) : x(x), y(y) {}

    friend class Rectangle; // 声明Rectangle类为友元类

private:
    int x;
    int y;
};

class Rectangle {
public:
    void showPoint(Point p) {
        cout << "Point: (" << p.x << ", " << p.y << ")" << endl;
    }
};

int main() {
    Point p(3, 4);
    Rectangle rect;
    rect.showPoint(p); // 输出: Point: (3, 4)

    return 0;
}

4. 内部类

在C++中,类中可以嵌套定义另一个类,被嵌套的类称为内部类(也称为嵌套类)。内部类可以访问外部类的所有成员,包括私有成员和保护成员。

#include <iostream>
using namespace std;

class Outer {
public:
    Outer(int num) : number(num) {}

    class Inner {
    public:
        void display(Outer o) {
            cout << "Number from Outer: " << o.number << endl;
        }
    };

private:
    int number;
};

int main() {
    Outer outer(42);
    Outer::Inner inner;
    inner.display(outer); // 输出: Number from Outer: 42

    return 0;
}

5. 匿名对象

在C++中,可以创建没有名称的临时对象,这些对象称为匿名对象。匿名对象通常在函数调用或表达式求值时使用,它们在语句结束后会被立即销毁。

#include <iostream>
using namespace std;

class Point {
public:
    Point(int x, int y) : x(x), y(y) {}

    void display() {
        cout << "Point: (" << x << ", " << y << ")" << endl;
    }

private:
    int x;
    int y;
};

int main() {
    // 匿名对象在语句结束后会被销毁
    Point(3, 4).display(); // 输出: Point: (3, 4)

    return 0;
}

6. 拷贝对象时的一些编译器优化

在C++中,当对象进行拷贝构造或赋值操作时,编译器可能会进行一些优化,以提高性能和减少不必要的拷贝。这些优化包括:

- 复制消除(Copy Elision)**:编译器优化,直接将对象初始化到目标地址,而不进行中间拷贝。这可以减少不必要的拷贝构造函数的调用。

- 移动语义(Move Semantics)**:对于临时对象或将要被销毁的对象,编译器会使用移动构造函数或移动赋值运算符来转移资源的所有权,而不是进行深拷贝。

#include <iostream>
#include <vector>
using namespace std;

class MyClass {
public:
    MyClass() { cout << "Default constructor" << endl; }
    MyClass(const MyClass& other) { cout << "Copy constructor" << endl; }
    MyClass(MyClass&& other) { cout << "Move constructor" << endl; }

    MyClass& operator=(const MyClass& other) {
        cout << "Copy assignment operator" << endl;
        return *this;
    }

    MyClass& operator=(MyClass&& other) {
        cout << "Move assignment operator" << endl;
        return *this;
    }
};

MyClass createObject() {
    return MyClass();
}

int main() {
    MyClass obj1;
    MyClass obj2(obj1); // 调用拷贝构造函数,复制消除可能会优化此处

    obj2 = createObject(); // 调用移动赋值运算符,复制消除可能会优化此处

    vector<MyClass> vec;
    vec.push_back(obj1); // 调用拷贝构造函数,复制消除可能会优化此处

    return 0;
}

7. 再次理解封装

封装是面向对象编程的重要特性之一,它将数据和操作封装在一个单元中,以实现数据的隐藏和安全性。通过访问权限修饰符(`public`、`private`和`protected`),我们可以控制类的成员对外部的可见性。

- `public`:公有成员,可以在类的外部访问。
- `private`:私有成员,只能在类的内部访问。
- `protected`:保护成员,类似于私有成员,但可以在派生类中访问。

封装使得类的使用者只需关注类的接口(公有成员函数),而不需要了解类的实现细节(私有成员)。这样可以提高代码的可维护性和灵活性。

#include <iostream>
using namespace std;

class BankAccount {
public:
    BankAccount(string owner, double balance) : ownerName(owner), balance(balance) {}

    void deposit(double amount) {
        balance += amount;
    }

    void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
        } else {
            cout << "Insufficient balance." << endl;
        }
    }

    void displayBalance() {
        cout << "Balance of " << ownerName << ": $" << balance << endl;
    }

private:
    string ownerName;
    double balance;
};

int main() {
    BankAccount account("Alice", 1000.0);
    account.displayBalance(); // 输出: Balance of Alice: $1000

    account.deposit(500);
    account.displayBalance(); // 输出: Balance of Alice: $1500

    account.withdraw(2000); // 输出: Insufficient balance.

    return 0;
}

通过本文的详细讨论,我们深入了解了构造函数、静态成员、友元、内部类、匿名对象以及拷贝对象时的编译器优化,以及封装在面向对象编程中的重要性。这些概念和特性是C++中面向对象编程的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值