C++11&QT复习 (六)

类型转换函数和类域

    • [**Day6-3 类型转换函数和类域**](#Day6-3 类型转换函数和类域)
      • [**1. 类型转换函数(Type Conversion Functions)**](#1. 类型转换函数(Type Conversion Functions))
        • [**1.1 概述**](#1.1 概述)
        • [**1.2 代码示例**](#1.2 代码示例)
        • [**1.3 关键优化**](#1.3 关键优化)
      • [**2. 类域(Class Scope)**](#2. 类域(Class Scope))
        • [**2.1 作用域 vs 可见域**](#2.1 作用域 vs 可见域)
        • [**2.2 代码示例**](#2.2 代码示例)
        • [**2.3 关键优化**](#2.3 关键优化)
      • [**3. 内部类(Nested Class)**](#3. 内部类(Nested Class))
        • [**3.1 内部类的定义**](#3.1 内部类的定义)
        • [**3.2 访问外部类的 `private` 成员**](#3.2 访问外部类的 private 成员)
        • [**3.3 静态内部类**](#3.3 静态内部类)
      • [**4. 作用域运算符(Scope Resolution Operator `::`)**](#4. 作用域运算符(Scope Resolution Operator ::)
        • [**4.1 访问全局变量**](#4.1 访问全局变量)
        • [**4.2 访问命名空间内的变量**](#4.2 访问命名空间内的变量)
        • [**4.3 访问类的静态成员**](#4.3 访问类的静态成员)
      • [**5. 类型转换运算符(Type Casting Operators)**](#5. 类型转换运算符(Type Casting Operators))
        • [**5.1 `static_cast` 用法**](#5.1 static_cast 用法)
        • [**5.2 `dynamic_cast` 用法**](#5.2 dynamic_cast 用法)
        • [**5.3 `const_cast` 用法**](#5.3 const_cast 用法)
        • [**5.4 `reinterpret_cast` 用法**](#5.4 reinterpret_cast 用法)
      • [**6. 关键字 `explicit` 与类型转换**](#6. 关键字 explicit 与类型转换)
        • [**6.1 隐式转换**](#6.1 隐式转换)
        • [**6.2 使用 `explicit` 禁止隐式转换**](#6.2 使用 explicit 禁止隐式转换)
      • [**7. 总结**](#7. 总结)

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

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

1.1 概述

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

  • 类的成员函数,不能是友元函数或非成员函数。
  • 没有参数列表 (即必须是 () 空参数)。
  • 没有返回类型声明 ,即不能显式声明 void 或其他返回类型。
  • 使用 return 语句返回目标类型的变量
1.2 代码示例
cpp 复制代码
#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 代码示例
cpp 复制代码
#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 内部类的定义
cpp 复制代码
#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

cpp 复制代码
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 静态内部类

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

cpp 复制代码
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 访问全局变量
cpp 复制代码
#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 访问命名空间内的变量
cpp 复制代码
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 访问类的静态成员
cpp 复制代码
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 用法
cpp 复制代码
void test_static_cast() {
    double num = 10.5;
    int intNum = static_cast<int>(num);
    cout << "Converted value: " << intNum << endl;
}
5.2 dynamic_cast 用法
cpp 复制代码
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 用法
cpp 复制代码
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 用法
cpp 复制代码
void test_reinterpret_cast() {
    int num = 65;
    char* ch = reinterpret_cast<char*>(&num);
    cout << "Reinterpreted value: " << *ch << endl;
}

6. 关键字 explicit 与类型转换

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

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

void test_implicit_conversion() {
    Demo obj = 10; // 隐式调用 Demo(int)
}
6.2 使用 explicit 禁止隐式转换
cpp 复制代码
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 关键字 可以防止构造函数的隐式转换。

相关推荐
学习是种信仰啊14 分钟前
QT计算器开发
开发语言·c++·qt
SNAKEpc1213818 分钟前
在MFC中使用Qt(四):使用属性表(Property Sheet)实现自动化Qt编译流程
c++·qt·mfc
island131422 分钟前
【#2】介绍第三方库
c++·rpc·json
郭涤生30 分钟前
Chapter 2:A Tale of Two Values_《clean architecture》notes
开发语言·c++·笔记
<但凡.1 小时前
C++修炼:string类的使用
开发语言·c++·算法
helbyYoung1 小时前
【零基础JavaScript入门 | Day7】三大交互案例深度解析|从DOM操作到组件化开发
开发语言·javascript
小张-森林人2 小时前
C#中,什么是委托,什么是事件及它们之间的关系
开发语言·c#
何似在人间5752 小时前
JAVA实现动态IP黑名单过滤
java·开发语言·tcp/ip·nacos·黑名单过滤
demonlg01122 小时前
Go 语言标准库中log模块详细功能介绍与示例
开发语言·后端·云原生·golang
用户878623683782 小时前
如何在原始工程中自定义类
qt