cpp_05_类_string类

发布时间:2023年12月23日

1? 类的定义

1.1? ?构造函数

? ? ? ? 定义:函数名必须与类名相同,且没有返回值类型?,连void也没有。

? ? ? ? 构造函数调用时间:

? ? ? ? 在定义对象的同时自动被调用,而且仅被调用一次

????????????????1)对象定义语句

????????????????2)new操作符

? ? ? ? 构造函数的作用:

????????????????1)设置? 对象的初始状态:定义对象的各个成员变量赋初值

? ? ? ? ? ? ? ? 2)执行? 在对象定义之初想实现的任何操作?。

// clsobj1.cpp
// 构造函数:(1)函数名必须与类名相同 (2)没有返回值类型
// 构造函数被调用的时间:定义对象的同时,自动被调用
// 构造函数的作用:定义对象的各个成员变量(造包子馅)
#include <iostream>
#include <cstring>
using namespace std;
class Human {
public:
    Human( /* Human* this */ int age=0, const char* name="无名") {
        // 在this所指向的内存空间中 定义m_age(给m_age分配内存空间),初值随机数
        // 在this所指向的内存空间中 定义m_name(给m_name分配内存空间),初值随机数
        cout << "Human类的构造函数被调用" << endl;
        m_age = age;
        strcpy( m_name, name );
    }
//    void setinfo( /* Human* this */ int age=0, const char* name="无名" ) { 
//        this->m_age = age;
//        strcpy( this->m_name, name ); 
//    }
    void getinfo( /* Human* this */ ) { 
        cout << "姓名:" << this->m_name << ", 年龄:" << this->m_age << endl;
    }
private:    
    int m_age; // 声明
    char m_name[256]; // 声明 
};
// 以上代码模拟类的设计者(标准库的类,第三方提供的类,自己设计的类)
// ------------------------
// 以下代码模拟类的使用者
int main( void ) {
    Human h(22,"张飞"); // 定义h (给h分配内存空间),利用h.Human(22,"张飞")

    cout << "h对象创建完毕" << endl; 
//    h.setinfo( 22,"zhangfei" ); 
    h.getinfo(); 
    return 0;

1.2? 对象的定义过程

? ? ? ? 定义对象,就是

? ? ? ? 1)给对象分配内存空间

? ? ? ? 2)并利用对象调用构造函数

? ? ? ? ? ? ? ? ? ? ? ? ①定义成员变量;

? ? ? ? ? ? ? ? ? ? ? ? ②执行用户在构造函数中书写的代码。

????????

2? 类的实例化(定义对象)的11种方法

2.1? 栈中,对象的定义和销毁

? ? ? ? 在栈中,定义单个对象:

? ? ? ? ? ? ? ? 01)类名? 对象;? ? //注意不要加空括号,加了误导编译器:返回值类型 函数名 形参表

? ? ? ? ? ? ? ? 02)类名? 对象( 实参表 );?

? ? ? ? 在栈中,定义对象数组:

? ? ? ? ? ? ? ? 03)类名? 对象数组[ 元素个数 ];?

? ? ? ? ? ? ? ? 04)类名? 对象数组[ 元素个数 ] = { 类名( 实参表 ), ... };? ? // 11)定义匿名对象,右值

? ? ? ? ? ? ? ? 05)类名? 对象数组[] = { 类名( 实参表 ), ...};?

2.2? 堆中,对象的定义和销毁

? ? ? ? 不是所有的匿名对象生命周期都短暂:new出来的对象(下面讲到),基类子对象

? ? ? ? 匿名的栈对象,生命周期短暂,语句级。

? ? ? ??

? ? ? ? 在堆中,定义/销毁单个对象

? ? ? ? ? ? ? ? 06)类名*? 对象指针 = new? 类名;? //定义相应类的堆对象,匿名对象。

????????????????07)类名*? 对象指针 = new? 类名();? //这里可以加空括号,同06,异于01

? ? ? ? ? ? ? ? 08)类名*? 对象指针 = new? 类名( 实参表 );?

? ? ? ? ? ? ? ? ? ? ? ? delete? 对象指针;

? ? ? ? 在堆中,定义/销毁对象数组

? ? ? ? ? ? ? ? 09)类名*? 对象数组指针 = new? 类名[ 元素个数 ];?

? ? ? ? ? ? ? ? 10)类名* 对象数组指针 = new? 类名[ 元素个数 ]{类名( 实参表 ), ...};? ? ?// 11标准

? ? ? ? ? ? ? ? ? ? ? ? delete[]? 对象数组指针;

// clsobj2.cpp 定义对象的11种方法
#include <iostream>
#include <cstring>
using namespace std;
class Human {
public:
    Human( /* Human* this */ int age=0, const char* name="无名") {
        // 在this所指向的内存空间中 定义m_age(给m_age分配内存空间),初值随机数
        // 在this所指向的内存空间中 定义m_name(给m_name分配内存空间),初值随机数
        cout << "Human类的构造函数被调用" << endl;
        m_age = age;
        strcpy( m_name, name );
    }
    void getinfo( /* Human* this */ ) { 
        cout << "姓名:" << this->m_name << ", 年龄:" << this->m_age << endl;
    }
private:    
    int m_age; // 声明
    char m_name[256]; // 声明 
};
// 以上代码模拟类的设计者(标准库的类,第三方提供的类,自己设计的类)
// ------------------------
// 以下代码模拟类的使用者
int main( void ) {
    Human(32,"马超").getinfo();

    Human h(22,"张飞"); // 定义h (给h分配内存空间),利用h.Human(22,"张飞")
    h.getinfo(); 

    Human h2; // 定义h2,利用h2.Human()
    h2.getinfo();

    Human h3[3]; // 定义了3个Human类对象,并分别利用这3个Human类对象.Human()
    for( int i=0; i<3; i++ ) {
        h3[i].getinfo();
    }

    Human h4[3] = { Human(22,"张飞"), Human(20,"赵云"), Human(25,"关羽") };
    for( int i=0; i<3; i++ ) {
        h4[i].getinfo();
    }

    Human h5[] = { Human(22,"张飞"), Human(20,"赵云"), Human(25,"关羽"), Human(45,"黄忠") };
    for( int i=0; i<sizeof(h5)/sizeof(h5[0]); i++ ) {
        h5[i].getinfo();
    }

    Human* ph = new Human; // 定义 Human类堆对象,利用 Human类堆对象.Human()
    (*ph).getinfo(); // ph->getinfo()
    delete ph;
    ph = NULL;

    Human* ph2 = new Human(); // 定义 Human类堆对象,利用 Human类堆对象.Human()
    (*ph2).getinfo();
    delete ph2;
    ph2 = NULL;

    Human* ph3 = new Human(18,"武松"); // 定义 Human类堆对象,利用 Human类堆对象.Human(18,"武松")
    (*ph3).getinfo();
    delete ph3;
    ph3 = NULL;

    Human*ph4 = new Human[3]; // 定义了 3个Human类堆对象,分别利用这3个Human类堆对象.Human()
    for( int i=0; i<3; i++ ) {
        ph4[i].getinfo();
    }
    delete[] ph4;
    ph4 = NULL;

    Human* ph5 = new Human[3]{ Human(18,"武松"), Human(19,"李逵"), Human(20,"鲁达") };
    for( int i=0; i<3; i++ ) {
        ph5[i].getinfo();
    }
    delete[] ph5;
    ph5 = NULL;

    return 0;
}

3? string类

? ? ? ? 是C++标准库中的类,在操作字符串方面优于char*? []? :

? ? ? ? ? ? ? ? 1)string类是c++类,而char* []的c痕迹明显;

? ? ? ? ? ? ? ? 2)string类可直接 = 赋值/初始化,而char* []要用strcpy()。

3.1? string类的5种使用方法

? ? ? ? string? s1( "hello" );? ? ? ? ? ?//触发构造函数

? ? ? ? string? s2( s1 );? ? ? ? ?????????// 等同于 string? s2 = s1;? ? 触发构造函数

? ? ? ? string? s3;? ? s3 = s2;? ? ? ? // 触发拷贝复制函数调用

? ? ? ? string? s4 = "hello";? ? ? ? ? // 触发类型转换操作

? ? ? ? string? s5;? ? s5 = "hello";? ? ? ? // 触发类型转换操作

// string_pre.cpp C++标准库设计的string类
#include <iostream>
using namespace std;

// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    string s1("hello"); // s1维护的字符串为"hello"
    cout << "s1:" << s1 << endl;

    // 如果在做初始化,并且“=”两边类型完全一致,那么=xxx 和 (xxx) 无差别
    
    string s2(s1); // = s1; // s2维护的字符串 和 s1维护的字符串 内容相同 
    cout << "s2:" << s2 << endl;
    
    string s3; // s3维护的字符串为空串
    cout << "s3被赋值前:" << s3 << endl;
    s3 = s2; // s3维护的字符串 和 s2维护的字符串 内容相同
    cout << "s3被赋值后:" << s3 << endl;

    // 只要“=”两边类型不一致,编译器首先要做类型转换操作

    string s4 = "hello"; // s4维护的字符串内容为"hello"
    cout << "s4:" << s4 << endl;
    
    string s5; // s5维护的字符串为空串
    s5 = "hello"; // s5维护的字符串内容为 "hello"
    cout << "s5:" << s5 << endl;
    return 0;
}

?

3.2? string类的内部实现原理

//string.cpp
#include <iostream>
using namespace std;

// C++标准库设计的string类(类中有一个私有成员变量 char*m_psz-->指向一个字符串)

// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    string s1("hello"); // 定义s1,利用s1.string("hello")--->s1维护的字符串为"hello"
    cout << "s1:" << s1 << endl;

    // 如果在做初始化,并且“=”两边类型完全一致,那么=xxx 和 (xxx) 无差别
    
    string s2 =s1; //(s1) // 定义s2,利用s2.string(s1)--->s2维护的字符串 和 s1维护的字符串 内容相同 
    cout << "s2:" << s2 << endl;
    
    string s3; // 定义s3,利用s3.string()--->s3维护的字符串为空串
    cout << "s3被赋值前:" << s3 << endl;

    // 如果在做赋值,并且“=”两边类型完全一致,那么将触发 operator= 函数的调用
    s3 = s2; // s3.operator=(s2) --->s3维护的字符串 和 s2维护的字符串 内容相同
    cout << "s3被赋值后:" << s3 << endl;

    // 不管是初始化还是赋值,只要“=”两边类型不一致,编译器首先要做类型转换操作

    string s4 = "hello"; 
    // 定义 匿名string类对象,利用 匿名string类对象.string("hello")--->匿名string类对象维护的字符串为"hello"
    // string s4 = 匿名string类对象--->s4维护的字符串 和 匿名string类对象维护的字符串 内容相同
    // --->s4维护的字符串内容为"hello"
    //模式相当于s1 + s2
    cout << "s4:" << s4 << endl;
    
    string s5; // 定义s5,利用s5.string() --->s5维护的字符串为空串
    s5 = "hello"; 
    // 定义 匿名string类对象,利用 匿名string类对象.string("hello")--->匿名string类对象维护的字符串为"hello"
    // s5 = 匿名string类对象--->s5维护的字符串 和 匿名string类对象维护的字符串 内容相同
    //--->s5维护的字符串内容为 "hello"
    cout << "s5:" << s5 << endl;
    return 0;
}

// twoDimensional.cpp 设计一个二维坐标系的 类
#include <iostream>
using namespace std;

class TwoDimensional {
public:
    TwoDimensional( int x=0, int y=0 ) {
        // 在this指向的内存空间中 定义m_x初值为随机数
        // 在this指向的内存空间中 定义m_y初值为随机数
        m_x = x;
        m_y = y;
    }
    void getinfo( /* TwoDimensional* this */ ) { // 非常函数
        cout << "横坐标: " << m_x << ", 纵坐标: " << m_y << endl;
    }
private:
    int m_x; // 横坐标
    int m_y; // 纵坐标
};

int main( void ) {
    TwoDimensional a(100,300); // 定义a,利用a.TwoDimensional(100,300)
    a.getinfo( );

    return 0;
}

文章来源:https://blog.csdn.net/qq_33331020/article/details/135169047
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。