C++11&QT复习 (六)

发布于:2025-03-26 ⋅ 阅读:(27) ⋅ 点赞:(0)

Day6-3 类型转换函数和类域

1. 类型转换函数(Type Conversion Functions)

1.1 概述

类型转换函数用于将类的对象转换为其他类型,满足以下特点:

  • 类的成员函数,不能是友元函数或非成员函数。
  • 没有参数列表(即必须是 () 空参数)。
  • 没有返回类型声明,即不能显式声明 void 或其他返回类型。
  • 使用 return 语句返回目标类型的变量
1.2 代码示例
#include <iostream>

using namespace std;

class Complex
{
    friend std::ostream& operator<<(std::ostream& os, const Complex& rhs);

public:
    Complex(int real = 0, int imag = 0)  
        : _real(real), _imag(imag)
    {
        cout << "Complex(int, int) 构造函数" << endl;
    }

    ~Complex()
    {
        cout << "~Complex 析构函数" << endl;
    }

    void display() const
    {
        cout << _real << " + " << _imag << "i" << endl;
    }

    int getReal() const { return _real; }
    int getImag() const { return _imag; }

private:
    int _real;
    int _imag;
};

// 重载输出运算符,使 Complex 可以被 cout 直接输出
std::ostream& operator<<(std::ostream& os, const Complex& rhs)
{
    os << rhs._real << " + " << rhs._imag << "i";
    return os;
}

class Point
{
    friend std::ostream& operator<<(std::ostream& os, const Point& rhs);

public:
    Point(int x = 0, int y = 0) : _x(x), _y(y)
    {
        cout << "Point(int, int) 构造函数" << endl;
    }

    // **类型转换函数**
    operator int() const
    {
        cout << "operator int()" << endl;
        return _x + _y;
    }

    operator double() const
    {
        cout << "operator double()" << endl;
        return _y == 0 ? 0.0 : static_cast<double>(_x) / _y;
    }

    operator Complex() const
    {
        cout << "operator Complex()" << endl;
        return Complex(_x, _y);
    }

    ~Point()
    {
        cout << "~Point 析构函数" << endl;
    }

    // **类型转换构造函数**
    explicit Point(const Complex& rhs)
        : _x(rhs.getReal()), _y(rhs.getImag())
    {
        cout << "Point(const Complex&) 类型转换构造函数" << endl;
    }

    void print() const
    {
        cout << "(" << _x << ", " << _y << ")" << endl;
    }

private:
    int _x;
    int _y;
};

// 重载输出运算符,使 Point 可以被 cout 直接输出
std::ostream& operator<<(std::ostream& os, const Point& rhs)
{
    os << "(" << rhs._x << ", " << rhs._y << ")";
    return os;
}

void testTypeConversion()
{
    Point pt(3, 4);
    cout << "Point pt: " << pt << endl;

    int intValue = pt;  
    cout << "转换为 int: " << intValue << endl;

    double doubleValue = pt;
    cout << "转换为 double: " << doubleValue << endl;

    Complex comValue = pt;
    cout << "转换为 Complex: " << comValue << endl;
}

int main()
{
    testTypeConversion();
    return 0;
}
1.3 关键优化

类型转换构造函数增加 explicit,防止隐式转换导致潜在错误。
类型转换函数添加 const,保证 Point 的成员变量不会被修改。
operator double() 处理 _y == 0 情况,避免除零异常。
优化 Complex 相关代码,消除 friend 冗余,提高可读性。


2. 类域(Class Scope)

2.1 作用域 vs 可见域
  • 作用域(Scope):指变量在代码中的可访问范围,影响变量的解析方式。
  • 可见域(Visibility):变量是否在当前上下文可见,受 privateprotectedpublic 修饰符影响。
  • 作用域 ≥ 可见域,如果没有命名冲突,二者相等。

2.2 代码示例
#include <iostream>

using namespace std;

int globalNumber = 50;  // **全局作用域变量**

namespace ceshi
{
    int namespaceNumber = 20;  // **命名空间作用域**

    class Test
    {
    public:
        Test(int value = 100) : number(value) {}

        void print(int number)
        {
            cout << "局部变量 number: " << number << endl;
            cout << "成员变量 number: " << this->number << endl;
            cout << "类作用域 number: " << Test::number << endl;
            cout << "命名空间 ceshi::number: " << ceshi::namespaceNumber << endl;
            cout << "全局变量 globalNumber: " << ::globalNumber << endl;
        }

    private:
        int number;  // **类成员变量**
    };
} // namespace ceshi

void testScope()
{
    int localValue = 3000;
    ceshi::Test obj;
    obj.print(localValue);
}

int main()
{
    testScope();
    return 0;
}
2.3 关键优化

清晰划分不同作用域:全局作用域 ::、命名空间 ceshi::、类作用域 this->Test::
增强 print() 方法输出格式,更直观理解变量的作用域。
消除不必要的析构函数,提升代码简洁性。
代码格式调整,增强可读性。


3. 内部类(Nested Class)

内部类(Nested Class)是指在一个类的定义内部再定义一个类。内部类在逻辑上属于外部类的一部分,但具有自己的作用域。

3.1 内部类的定义
#include <iostream>
using namespace std;

class Outer {
public:
    class Inner { // 内部类
    public:
        void display() {
            cout << "This is Inner class" << endl;
        }
    };
};

void test() {
    Outer::Inner obj; // 创建内部类对象
    obj.display();
}

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

特点:

  1. 内部类的作用域受外部类的限制。
  2. 内部类的对象可以通过 外部类::内部类 的方式创建。
  3. 内部类可以访问外部类的 publicprotected 成员,但不能直接访问 private 成员(除非使用 friend 关键字)。
3.2 访问外部类的 private 成员

如果内部类需要访问外部类的 private 成员,可以将其声明为 friend

class Outer {
private:
    int _data = 10;

public:
    class Inner {
    public:
        void display(Outer& obj) {
            cout << "Outer data: " << obj._data << endl;
        }
    };
};

void test2() {
    Outer outerObj;
    Outer::Inner innerObj;
    innerObj.display(outerObj);
}
3.3 静态内部类

静态内部类不能访问外部类的非静态成员。

class Outer {
public:
    static class StaticInner {
    public:
        void show() {
            cout << "This is a static inner class" << endl;
        }
    };
};

void test3() {
    Outer::StaticInner obj;
    obj.show();
}

4. 作用域运算符(Scope Resolution Operator ::

作用域运算符 :: 用于指定变量、函数或类所属的作用域,主要应用如下:

4.1 访问全局变量
#include <iostream>
using namespace std;

int number = 100;

void test() {
    int number = 50;
    cout << "Local number: " << number << endl;
    cout << "Global number: " << ::number << endl;
}
4.2 访问命名空间内的变量
namespace A {
    int value = 10;
}

namespace B {
    int value = 20;
}

void test2() {
    cout << "A::value = " << A::value << endl;
    cout << "B::value = " << B::value << endl;
}
4.3 访问类的静态成员
class Demo {
public:
    static int data;
};

int Demo::data = 50;

void test3() {
    cout << "Static data: " << Demo::data << endl;
}

5. 类型转换运算符(Type Casting Operators)

C++ 提供了四种类型转换运算符:

  1. static_cast:用于基本类型之间的转换。
  2. dynamic_cast:用于多态类型的安全转换。
  3. const_cast:用于去除 constvolatile 修饰符。
  4. reinterpret_cast:用于不同类型指针之间的转换。
5.1 static_cast 用法
void test_static_cast() {
    double num = 10.5;
    int intNum = static_cast<int>(num);
    cout << "Converted value: " << intNum << endl;
}
5.2 dynamic_cast 用法
class Base {
public:
    virtual void show() {}
};

class Derived : public Base {
public:
    void show() {
        cout << "Derived class" << endl;
    }
};

void test_dynamic_cast() {
    Base* basePtr = new Derived();
    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
    if (derivedPtr) {
        derivedPtr->show();
    }
    delete basePtr;
}
5.3 const_cast 用法
void test_const_cast() {
    const int num = 42;
    int* ptr = const_cast<int*>(&num);
    *ptr = 10;
    cout << "Modified value: " << *ptr << endl;
}
5.4 reinterpret_cast 用法
void test_reinterpret_cast() {
    int num = 65;
    char* ch = reinterpret_cast<char*>(&num);
    cout << "Reinterpreted value: " << *ch << endl;
}

6. 关键字 explicit 与类型转换

默认情况下,C++ 允许构造函数进行隐式类型转换,但 explicit 关键字可以禁止这种行为。

6.1 隐式转换
class Demo {
public:
    Demo(int x) { cout << "Demo(int)" << endl; }
};

void test_implicit_conversion() {
    Demo obj = 10; // 隐式调用 Demo(int)
}
6.2 使用 explicit 禁止隐式转换
class Demo {
public:
    explicit Demo(int x) { cout << "Demo(int)" << endl; }
};

void test_explicit() {
    // Demo obj = 10; // 错误!隐式转换被禁止
    Demo obj(10);    // 正确
}

7. 总结

  1. 内部类 是定义在另一个类内部的类,具有自己的作用域,并且可以是 static
  2. 作用域运算符 :: 用于访问不同作用域的变量或函数。
  3. 类型转换运算符 提供更安全、可控的转换方式。
  4. explicit 关键字 可以防止构造函数的隐式转换。