基于C++程序设计(原书第3版)进行大一期末C++快速复习(第三部分)

第八章多维数组

声明二维数组

  1. 静态声明并初始化(指定大小)

    // 声明并初始化一个3行4列的二维整数数组
    int arr[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };

    这种情况下,编译器会根据初始化列表推断数组的大小,如果没有提供初始化列表,则需要显式指定每一维的大小。

  2. 只声明不初始化(指定大小)

    // 声明一个3行4列的二维数组
    int arr[3][4];

    在使用前必须为数组的所有元素分配值,因为没有默认初始化。
    注:这里主要看第二部分中的二维数组

操作二维数组

matrix函数声明

const int ROW_SIZE=10;
const int COLUMN_SIZE=10;
int matrix [ROW_SIZE][COLUMN_SIZE];

用输入值初始化函数

用for循环

for(int i=0;i>matrix[i][j];   
    }
}

用随机数初始化数组

for(int row=0;i

打印数组

for(int row=0;i

求所有元素的和

int total=0;
for(int row=0;i

按列求元素的和

for(int column=0;column

求哪行元素和最大

int maxRow=0;
int indexOfMaxRow=0;//行号
for(int column=0;columnmaxRow)
    {
        maxRow=totalOfThisRow;
        indexOfMaxRow=row;
    }
    
}

cout<<"Row"<

随机洗牌

srand(time(0));
for(int i=0;i

二维数组作为函数参数

例:计算矩阵中所有元素之和

基于C++程序设计(原书第3版)进行大一期末C++快速复习(第三部分)_第1张图片

第九章对象和类

类的声明,定义类和创建对象

//利用类输出圆的面积和周长
class Circle
{
    private://决定了成员的访问权限
        float r,s,l;//数据成员 数据成员定义了对象的属性
        //  被private设置的数据成员只能在类内被访问
    public://决定了成员的访问权限
        void setr(float r1){r=r1;}
        void area(){s=3.14*r*r;}
        void lenth(){l=2*3.14*r;}
        void print()
        {   cout<<"r="<// 声明一个名为Person的类及其构造函数
class Person {
public:
    // 构造函数声明和定义
    Person(string name, int age);  // 参数列表用于初始化对象的状态

private:
    string m_name;
    int m_age;
};

// 构造函数的实现
Person::Person(string name, int age) : m_name(name), m_age(age) {
    // 这里可以添加任何必要的初始化代码,但通常情况下,初始化列表就足够了
}

// 使用构造函数创建对象
int main() {
    Person p("Alice", 25);
    // 此时,p对象的m_name成员变量被初始化为"Alice",m_age被初始化为25
    return 0;
}

注:类中构造函数是为了给私有数据成员赋值 

创建和使用对象

对象的数据域和函数可用对象名通过点运算符(.)来访问。

#include
using namespace std;

class Circle {
private:
    double radius; // 半径
public:
    // 无参构造函数
    Circle() {
        radius = 1.0;
    }

    // 带参数的构造函数
    Circle(double r) : radius(r) {}

    // 拷贝构造函数,用于对象间的复制
    Circle(const Circle& other) {
        radius = other.radius;
    }

    // 获取面积的方法
    double getArea() {
        return 3.14159 * radius * radius;
    }
};

int main() {
    // 使用无参构造函数创建匿名对象,并通过赋值运算符进行复制
    Circle circle1 = Circle(); // 匿名对象
    Circle circle2 = Circle(); // 另一个匿名对象

    // 输出两个圆的面积
    cout << "Circle1's area: " << circle1.getArea() << endl;
    cout << "Circle2's area: " << circle2.getArea() << endl;

    // 使用带参数的构造函数创建名为 circle3 的对象
    Circle circle3(5.0);

    // 输出 circle3 的面积
    cout << "Circle3's area: " << circle3.getArea() << endl;

    return 0;
}

在上述示例中:

  1. Circle() 创建了一个匿名 Circle 对象,其半径默认为 1.0。
  2. 将这个匿名对象的内容通过拷贝构造函数复制给 circle1 和 circle2
  3. Circle(5.0) 创建了一个具有特定半径(5.0)的匿名 Circle 对象,然后将其内容复制给 circle3

最后,我们通过对象名 circle1circle2 和 circle3 调用它们的 getArea() 方法来获取各自对应的圆面积。

类定义和类实现的分离

在C++中,类定义和类实现的分离是一种良好的编程实践,它有助于模块化设计、提高代码复用性和可维护性。具体做法是将类的声明(接口)放在头文件(通常扩展名为.h.hpp),而将类成员函数的实现放在源文件(通常扩展名为.cpp)。

类定义(头文件,如Circle.h):

// Circle.h
#ifndef CIRCLE_H // 防止多次包含
#define CIRCLE_H

class Circle {
public:
    // 构造函数声明
    Circle(double radius);
    
    // 成员函数声明
    double getArea();
    void setRadius(double newRadius);

private:
    double radius; // 数据成员(属性)
};

#endif // CIRCLE_H

类实现(源文件,如Circle.cpp):

// Circle.cpp
#include "Circle.h"

// 构造函数实现
Circle::Circle(double r) : radius(r) {}

// 成员函数实现
double Circle::getArea() {
    return 3.14159 * radius * radius;
}

void Circle::setRadius(double newRadius) {
    radius = newRadius;
}

这样做的好处:

  • 头文件提供了类的接口描述,允许其他编译单元(比如主程序或其他类的实现文件)看到类的数据成员和成员函数原型,从而能够使用这个类来创建对象并调用其方法。
  • 源文件则包含了具体的函数实现,确保了类的具体实现细节可以被隐藏起来,遵循了信息隐藏的原则,同时避免了在每个包含头文件的地方都引入不必要的编译负担。
  • 类定义和实现分离后,可以分别编译头文件和源文件,然后通过链接阶段把它们组合成一个完整的可执行程序。这有利于项目的组织和大型软件工程的分工合作。

类中的内联函数

如果一个函数是在类定义内实现的,那它自动成为一个内联函数,这也称为“内联定义”。


class Circle {
public:
    // 成员函数声明并内联
    inline double getArea() const {
        return 3.14159 * radius * radius;
    }

private:
    double radius; // 数据成员(属性)
};
  1. 私有(private)成员

    • 私有成员是类内部使用的数据成员或函数,外部无法直接访问。这是实现封装的主要手段。
      class Circle {
      private:
          double radius; // 半径,作为私有数据成员
      public:
          // 公共接口(构造函数、getter/setter等)
          Circle(double r);
          double getRadius() const;
          void setRadius(double newRadius);
          // ...
      };
  2. 公共(public)成员

    • 公共成员是可以被任何代码访问的成员,包括数据成员和成员函数。通常用于提供对类功能的外部接口。​​​​​​​
      class Circle {
      private:
          double radius;
      public:
          Circle(double r); // 构造函数是公共的,用于初始化半径
          double getArea(); // 获取面积的函数也是公共的
      };

变量作用域

虽然类成员可以按任意顺序声明,但最好的方式是先声明公有成员,再声明私有成员。

class Circle {
public:
    double radius; // 数据成员在整个类的范围内可见

    void setRadius(double r) {
        radius = r; // 在成员函数setRadius()中可以直接访问radius
    }

private:
    int id; // 即使id是私有的,它也在类的内部作用域内
};

类抽象和封装

类抽象(Class Abstraction)

  • 类抽象是指通过定义一个类来描述一类具有共同特征的事物,这个类包含了该类事物的属性(数据成员)和行为(成员函数)。类抽象的关键在于识别出实体的本质特征,并忽略非本质细节。例如,定义一个Circle类,它可能包含半径(radius)这一属性和计算面积(getArea)的行为,而不会关注圆的具体绘制或渲染方式。
  • 通过类抽象,程序员可以专注于问题领域中的核心概念和逻辑,从而提高代码的可读性、可维护性和复用性。
class Circle {
public:
    double radius; // 数据成员(属性)
    Circle(double r); // 构造函数

    double getArea(); // 计算并返回面积的方法
};

封装(Encapsulation)

  • 封装是将数据(状态)和操作这些数据的函数捆绑在一起,并对数据进行保护的过程。在C++中,通常使用访问修饰符(public、private和protected)来实现封装。
  • 私有成员变量(private data members)只能被类内部的成员函数访问,外部无法直接访问。公有成员函数(public member functions)则提供了与外界交互的接口,允许外部代码通过这些函数来间接操作私有数据,同时限制了对数据的不当修改。
class Circle {
private: // 使用private关键字封装内部数据
    double radius;

public:
    Circle(double r) : radius(r) {} // 构造函数初始化私有成员

    // 公共方法提供对私有数据的操作
    double getRadius() const { return radius; } // 获取半径的getter方法
    void setRadius(double newRadius) { radius = newRadius; } // 设置半径的setter方法

    double getArea() const { return 3.14159 * radius * radius; } // 计算并返回面积的方法
};

在这个例子中,radius是私有的,外部不能直接修改它的值,而是必须通过setRadius()方法来进行安全的设置。同时,获取半径的值也只能通过getRadius()方法获取,这就是封装的应用。

成员初始化列表

Rclass (double a=1,double =2):h(a),w(b){cout<<"******"<

 析构函数的使用(先创建的后撤销,后创建的先撤销)

定义与命名规则:

  • 析构函数的名称与其所在类名相同,但在其前面添加一个波浪符(tilde ~)。
  • 例如,在类 MyClass 中,析构函数的声明如下:
class MyClass {
public:
    // 构造函数
    MyClass() {}

    // 析构函数
    ~MyClass() {
        // 清理和释放资源的代码放在这里
    }

    // 其他成员函数...
};

作用与使用场景:

  1. 当一个局部非静态对象离开其作用域时(如函数执行完毕或控制结构结束),系统会自动调用该对象的析构函数。
  2. 当动态分配的对象(通过 new 关键字创建)不再需要时,程序员必须显式地调用 delete 进行删除操作,此时也会调用析构函数。
  3. 对于容器中的对象(如 std::vector 或 std::list),当元素从容器中移除或容器本身被销毁时,对应的析构函数也会被调用。

示例用法:

#include 

class Resource {
public:
    Resource() { std::cout << "Resource created.\n"; }
    ~Resource() { std::cout << "Resource destroyed.\n"; }

    // 示例资源管理操作
    void useResource() const { /* 使用资源 */ }
};

int main() {
    // 局部对象的析构
    {
        Resource r; // 创建资源
        r.useResource(); // 使用资源
        // 当此处的大括号结束时,r将超出作用域,析构函数会被调用
    } // 输出: "Resource destroyed."

    // 动态分配对象的析构
    Resource* pR = new Resource(); // 动态创建资源
    pR->useResource();
    delete pR; // 显式释放资源,析构函数被调用

    return 0;
}

在上述示例中,每当一个 Resource 类型的对象被销毁时,其析构函数都会被调用以确保资源得到适当的清理和释放。

类内声明和类外定义

类内声明: 类内声明是指在类的定义体内部声明成员函数,但不提供实现。这通常用于声明构造函数、析构函数、以及其他成员函数的原型。例如:

class MyClass {
public:
    // 构造函数声明
    MyClass(int value);
    
    // 成员函数声明
    void doSomething();
    
private:
    int myData;
};

类外定义: 类外定义是在类定义之外定义上述声明过的成员函数。这样做的好处是可以保持类的定义简洁,并且可以将实现细节分散到不同的文件中以支持模块化编程。

// 在类外定义构造函数
MyClass::MyClass(int value) : myData(value) {}

// 在类外定义成员函数
void MyClass::doSomething() {
    // 函数的具体实现
    cout << "Doing something with: " << myData << endl;
}

总结来说,类内声明告诉编译器类具有哪些成员函数,而类外定义则是提供了这些函数的实际代码实现。这样做符合了“声明-定义分离”的原则,有助于提高代码可读性和组织性,以及便于进行源代码管理。

结构体

结构体能够将不同数据类型组成一个部分

//求5个学生成绩的平均分
struct student
{
    char name[20];
    int math;
    int english;
    int c;
    int total;
    float eve;
};

int main()
{
    struct student stu[5];//在程序中定义一个名为 stu 的数组,该数组包含5个 struct student 类型的元素    数组是student类型
    //该数组有一个元素都具有该结构体的5部分
    cout<<"name "<<"\tmath "<<"\tenglish "<<"\tc :"<>stu[i].name>>stu[i].math>>stu[i].english>>stu[i].c;
    }
    for(int i=0;i<5;i++)
    {
        stu[i].total=stu[i].math+stu[i].english+stu[i].c;
        stu[i].eve=stu[i].total/3.0;
       
    }
    for(int i=0;i<5;i++)
    {
        cout <<\tstu[i].name<<\tstu[i].math<<\tstu[i].english<<\tstu[i].c;
    }
    return 0;
}

指针与结构体

struct student
{
    char name[20];
    int math;
    int english;
    int c;
    int total;
    float eve;
};
int main()
{
    int m;// float *p1=&m wrong 因为数据类型不同
    struct studnet s1,s2;//s1,s2分别占用不同的内存空间
    struct student *p;//此时p只能指向student定义的变量  p=&m;wrong
    p=&s1;//p保存的是s1的起始地址即name

    p->c=70;//-> 符号是一个成员访问操作符,用于访问指向对象的指针的成员(如变量或函数)。
//当您有一个指向结构体或类实例的指针 p,并且想要访问该实例的成员 c 时,可以使用 -> 符号
    p=&s2;//p指向s2
    p->c=66;
    cout<
//在C++中利用结构体和指针输出元素周期表前三个元素的元素名称,元素序号和原子量
// 定义一个结构体来存储元素的信息
struct Element
{
    std::string name;
    int atomic_number;
    double atomic_weight;
};

int main()
    {
    // 初始化前三个元素的结构体数组
    Element elements[] = {
        {"Hydrogen", 1, 1.008},
        {"Helium", 2, 4.003},
        {"Lithium", 3, 6.941}
    };

  // 创建一个指向元素数组的指针
    Element* element_ptr = elements;

    // 使用指针输出前三个元素的名称、序号和原子量
    for (int i = 0; i < 3; i++)
    {
        cout << "Element Name: " << element_ptr->name << endl;
        cout << "Atomic Number: " << element_ptr->atomic_number << endl;
        cout << "Atomic Weight: " << element_ptr->atomic_weight << endl;
        cout << std::endl;

        // 移动指针到下一个元素
        element_ptr++;
    }

    return 0;
}

共用体变量

使用公用体可以节省内存空间。因为公用体中的所有成员共享同一块内存区域,所以它的大小等于其中最大成员的大小。 


union student1//union定义的共用体变量成员公用一个存储空间
{
    char name[20];
    int math;
    int english;
    int c;
    int total;
    float eve;
};

 若有侵权,请联系作者

你可能感兴趣的:(c++)