PoEdu培训 C++班 第三课 C过度到C++(3) & 类和对象
文章类别: 培训笔记 0 评论

PoEdu培训 C++班 第三课 C过度到C++(3) & 类和对象

文章类别: 培训笔记 0 评论

C过渡到C++(3)

接上一篇博文

引用

引用是变量的一个别名.

我们来看一下指针

指针是一种数据类型.

看个引用的例子
#include <iostream>

// 引用例子
void Swap(int &iValA, int &iValB)
{
    int iTmp = iValB;
    iValB = iValA;
    iValA = iTmp;
}

int main()
{
    int iVal = 100;
    int &refVal = iVal;

    std::cout << "iVal:";
    std::cout << iVal;
    std::cout << "RefVal:";
    std::cout << refVal;

    int iNum = 50;
    refVal = num;   // 相当于  iVal = num;

    // 此时 是能正常进行交换的
    Swap(iVal, iNum);

    return 0;
}

为了更加好理解, 可以这么想: 引用是一个阉割版的指针
它更加的安全, 拥有类型检查, 拥有长度检查

const小知识

// 猜猜谁不能被修改?
int main() 
{
    int iVal = 100;
    const int* pVal = &iVal; // 值不能修改
    int const* pVal = &iVal; // 值不能修改
    int* const pVal = &iVal; // 地址不能修改
    return 0;
}

记住, const是左结合

常量引用

// 常量引用例子
int main()
{
    const int num = 500;
    const int& refNum = num;

    return 0;
}

注意

int main()
{
    const int& num = 500;
    const int* pNum = &num;

    // 在VS编译器中, 它会在常量区分配空间存储500...

    return 0;
}

这个操作是无意义的
它属于未定义的行为
它依托于编译器的处理
十分不建议这样的代码

按引用传递

// 引用传值
#include <iostream>


void Swap(int &iValA, int &iValB)
{
    int iTmp = iValB;
    iValB = iValA;
    iValA = iTmp;
}

int main()
{
    int iVal = 100;
    int iNum = 50;

    // 引用传值
    Swap(iVal, iNum);

    return 0;
}

函数之间的值传递是通过来完成的.
在参数是引用的话, 传递的实际上是地址
结构体作为参数的时候, 使用引用是比较好的.
但是, 风险是可能会修改外部的变量
所以, 基本上会使用常量引用来进行参数传递.
安全, 高效

// 引用传值
#include <iostream>


void Dosomething(const int &iValA, const int &iValB)
{
    // ...
}

int main()
{
    int iVal = 100;
    int iNum = 50;

    // 引用传值
    Dosomething(iVal, iNum);
    // iVal 和 iNum 都不会有变化

    return 0;
}

引用作为返回值

// 返回引用例子
#include <iostream>

int iArray[] = {0, 1, 3, 5 };

int& Index(int idx)
{
    return iArray[idx];
}

int* Index2(int idx)
{
    return &iArray[idx];
}

int main()
{
    Index(0) = 100;
    *Index(1) = 50;

    std::cout << iArray[0] << "   " << iArray[1];

    return 0;
}

引用和指针

引用可以代替任何传值类的指针参数. ???
引用不能代替指针!.
引用无法指向堆区.

引用的冷知识

// 指针的引用
int main()
{
    int iNum = 0;
    int* p = &iNum;
    int *&refp = p;
    
    return 0;
}

auto

auto 是C11中加入的全新变量类型
它会自动推导所需要的类型.

    //永远不要写如下代码
    int iNum = 0;
    int* p = &iNum;
    auto &refP = p;

类和对象

我们先从广义上来理解一下 类.
比如人类, 人类是一个种类, 拥有一些共同的特征和能力.
共有的一些特征, 我们称之为 "属性"
共同的一些能力, 我们称之为 "方法"
人类, 是一个抽象出来, 具有共性的一个类别, 我们称之为 "类"

在C++中, 使用class关键字来进行类的声明.
类中的属性, 就是一些变量
类中的方法, 就是我们的函数

类是"虚"的, 在我们的C++中, 它是不占用内存的

类的种类

类可以分为抽象类工具类.
抽象类

抽象类就是我们对一些共同的特点(变量)和行为(方法)进行抽象而得到的类.
想要写一个抽象类, 需要知道这个类想要表示的是什么, 需要根据业务来定

工具类

工具栏是把我们一些零散或常用或具有某一类特定功能的方法组织到一起产生的类.
典型的代表: string类

类的访问权限

私有 private

类的访问权限默认是私有的.
private
是只有在类内部才能访问的.

公有 public

public
类的内外部都可以访问.

保护 protected

protected

访问权限让我们对类的可控性更强

构造函数和析构函数

构造函数

① 单纯的构造函数讨论, 不包括单例模式类似的解决方案

析构函数

对象

我们从广义上来理解一下 对象.
我们每一个人, 都是一个对象.
我们都具备人类的特征和能力.
我们每个都是具象的, 都是真实存在的.

在C++中, 使用 类名 变量名; 就能创建一个对象.

对象是"真实存在"的, 在我们的C++中, 它是占用内存的

类和对象的使用


#include <iostream>
#include <cstring>

class HadesString 
{
// 默认是私有的访问权限
// private:
    // 属性

    char* _szStr;
    int _iLen;

    // 方法
public:
    // 构造函数
    HadesString()
    {
        std::cout << "HadesString()被调用" << std::endl;
        _szStr = new char[100];
    }

    HadesString(char* str)
    {
        _iLen = strlen(str);
        _szStr = new char[_iLen + sizeof(char)];
        strcpy(_szStr, str);
    }

    // 析构函数
    ~HadesString()
    {
        std::cout << "~HadesString()被调用" << std::endl;
        delete[] _szStr;
    }

    int& Len()
    {
        return _iLen;
    }

    char* GetString()
    {
        return _szStr;
    }

};

int main()
{
    HadesString str("Hello Hades!");

    str.Len() = 10;
    std::cout << str.GetString() << std::endl;
    return 0;
}

未完待续

如有错误,请提出指正!谢谢.

回复