[C++] 基础教程 - 什么是struct和class,以及它们有什么区别?

什么是C++的struct?

C++中保留了C语言的 struct 关键字,并且加以扩充。在C语言中,struct 只能包含成员变量,不能包含成员函数。而在C++中,struct 类似于 class,既可以包含成员变量,又可以包含成员函数。

C++的struct(结构体)是一种用户自定义的数据类型,它可以包含多个不同类型的数据成员。结构体的主要作用是将一组相关的数据组织起来,以便于程序中的其他部分使用。

在C++中,定义一个结构体的语法如下:

struct 结构体名 {
    数据类型1 成员名1;
    数据类型2 成员名2;
    ...
};

例如,我们可以定义一个表示二维坐标的结构体:

struct Point {
    int x;
    int y;
};

这个结构体包含了两个整数类型的成员变量x和y,用于表示二维平面上的点的横纵坐标。我们可以创建这个结构体的实例,并访问它的成员变量:

#include <iostream>

int main() {
    // 创建一个Point结构体的实例
    Point p1;
    p1.x = 3;
    p1.y = 4;

    // 输出Point结构体的实例的信息
    std::cout << "Point p1: (" << p1.x << ", " << p1.y << ")" << std::endl;

    return 0;
}

此外,结构体还可以包含构造函数、析构函数、拷贝构造函数、赋值运算符重载等成员函数,以实现更丰富的功能。

例子:

#include <iostream>

// 定义一个结构体Person
struct Person {
    // 默认构造函数
    Person() {
        std::cout << "Person constructor called." << std::endl;
    }

    // 带参数的构造函数
    Person(const std::string& name, int age) : name_(name), age_(age) {
        std::cout << "Person constructor called with parameters." << std::endl;
    }

    // 拷贝构造函数
    Person(const Person& other) : name_(other.name_), age_(other.age_) {
        std::cout << "Person copy constructor called." << std::endl;
    }

    // 赋值运算符重载
    Person& operator=(const Person& other) {
        if (this == &other) {
            return *this;
        }

        name_ = other.name_;
        age_ = other.age_;

        std::cout << "Person assignment operator called." << std::endl;

        return *this;
    }

    // 析构函数
    ~Person() {
        std::cout << "Person destructor called." << std::endl;
    }

    // 成员函数
    void introduce() const {
        std::cout << "Hello, my name is " << name_ << " and I am " << age_ << " years old." << std::endl;
    }

private:
    std::string name_;
    int age_;
};

int main() {
    // 使用默认构造函数创建一个Person实例
    Person p1;
    p1.introduce();

    // 使用带参数的构造函数创建一个Person实例
    Person p2("Alice", 30);
    p2.introduce();

    // 使用拷贝构造函数创建一个Person实例
    Person p3(p2);
    p3.introduce();

    // 使用赋值运算符重载修改一个Person实例的属性
    p2 = p3;
    p2.introduce();

    return 0;
}

在这个例子中,我们定义了一个名为Person的结构体,它包含了默认构造函数、带参数的构造函数、拷贝构造函数、赋值运算符重载和析构函数等成员函数。在main函数中,我们分别使用了这些成员函数来创建、修改和销毁Person实例。

什么是C++的class?

C++的class(类)是一种用户自定义的数据类型,它可以包含数据成员和成员函数。类提供了一种封装数据和操作数据的方法,使得程序更加模块化、易于维护和扩展。类是面向对象编程(OOP)的基本概念之一,它支持继承、多态等特性。

举例说明:

我们可以定义一个表示矩形的类,它包含长度和宽度两个数据成员,以及计算面积和周长的成员函数。

#include <iostream>
using namespace std;

// 定义一个表示矩形的类
class Rectangle {
public:
    // 构造函数
    Rectangle(double length, double width) : length_(length), width_(width) {}

    // 成员函数:计算面积
    double getArea() const {
        return length_ * width_;
    }

    // 成员函数:计算周长
    double getPerimeter() const {
        return 2 * (length_ + width_);
    }

private:
    // 数据成员:长度和宽度
    double length_;
    double width_;
};

int main() {
    // 创建一个矩形对象
    Rectangle rect(3.0, 4.0);

    // 调用成员函数计算面积和周长,并输出结果
    cout << "Area: " << rect.getArea() << endl;
    cout << "Perimeter: " << rect.getPerimeter() << endl;

    return 0;
}

在这个例子中,我们定义了一个名为Rectangle的类,它包含了两个私有数据成员length_和width_,以及两个公有成员函数getArea()和getPerimeter(),分别用于计算矩形的面积和周长。在main函数中,我们创建了一个Rectangle对象rect,并调用它的成员函数来计算面积和周长,然后输出结果。

C++struct和class有什么不同?

C++的struct和class在很多方面是相似的,它们都可以包含数据成员和成员函数,支持继承、多态等特性。但是,它们之间也存在一些不同之处,

默认访问权限:使用 class 时,类中的成员默认都是 private 属性的;而使用 struct 时,结构体中的成员默认都是 public 属性的。

继承方式:class 继承默认是 private 继承,而 struct 继承默认是 public 继承。

能否使用模板:class 可以使用模板,而 struct 不能(经测试,MSVC中,struct也能使用模板?)。

下面针对每个不同的地方举例说明:

默认访问权限不同

struct的默认访问权限是public,而class的默认访问权限是private。这意味着在struct中定义的成员变量和成员函数可以被任何代码访问,而在class中定义的成员变量和成员函数只能被该类的成员函数或友元函数访问。

例如:

// struct
struct Point {
    int x;
    int y;
};

// class
class Circle {
private:
    int radius;
public:
    int getRadius() const { return radius; }
    void setRadius(int r) { radius = r; }
};

在这个例子中,Point结构体中的x和y成员变量可以直接被其他代码访问,而Circle类中的radius成员变量只能被该类的成员函数或友元函数访问。

继承方式不同

struct可以隐式地继承自其父struct,而class必须显式地继承自另一个class或实现一个接口(即抽象类)。

例如:

// struct
struct Shape {
    virtual double area() const = 0;
};

struct Circle : public Shape {
    double radius;
    double area() const override { return 3.14 * radius * radius; }
};

struct Rectangle : public Shape {
    double width;
    double height;
    double area() const override { return width * height; }
};

// class
class Shape {
public:
    virtual double area() const = 0;
};

class Circle : public Shape {
private:
    double radius;
public:
    double getRadius() const { return radius; }
    void setRadius(double r) { radius = r; }
    double area() const override { return 3.14 * radius * radius; }
};

class Rectangle : public Shape {
private:
    double width;
    double height;
public:
    double getWidth() const { return width; }
    void setWidth(double w) { width = w; }
    double getHeight() const { return height; }
    void setHeight(double h) { height = h; }
    double area() const override { return width * height; }
};

在这个例子中,Shape是一个抽象类,它定义了一个纯虚函数area(),表示所有继承自Shape的类都必须实现这个函数。Circle和Rectangle都是Shape的子类,它们分别实现了area()函数。在struct中,我们可以使用隐式继承来实现这一点,而在class中,我们需要显式地继承Shape并实现area()函数。

class 可以使用模板,而 struct 不能?

C++中的class可以用于模板,这意味着我们可以使用相同的类定义来处理不同类型的数据。下面是一个使用模板的简单示例:

#include <iostream>
using namespace std;

// 定义一个模板类
template <typename T>
class MyClass {
public:
    // 构造函数
    MyClass(T value) : m_value(value) {}

    // 获取值的函数
    T getValue() const { return m_value; }

    // 设置值的函数
    void setValue(T value) { m_value = value; }

private:
    T m_value; // 存储数据的成员变量
};

int main() {
    // 使用int类型创建MyClass对象
    MyClass<int> intObj(10);
    cout << "intObj value: " << intObj.getValue() << endl;
    intObj.setValue(20);
    cout << "intObj value: " << intObj.getValue() << endl;

    // 使用double类型创建MyClass对象
    MyClass<double> doubleObj(3.14);
    cout << "doubleObj value: " << doubleObj.getValue() << endl;
    doubleObj.setValue(6.28);
    cout << "doubleObj value: " << doubleObj.getValue() << endl;

    return 0;
}

在这个例子中,我们定义了一个名为MyClass的模板类,它可以接受任意类型的参数T。然后我们在main函数中分别使用int和double类型创建了两个MyClass对象,并演示了如何使用这些对象的成员函数。这个例子展示了如何使用模板来实现泛型编程,使得我们的代码可以处理不同类型的数据。

template不能用于struct么?在VS VC++项目中亲测,把上面的例子的class修改为struct,也是可以通过的。

何时使用struct,何时使用class?

C++ 没有抛弃C语言中的 struct 关键字,其意义就在于给C语言程序开发人员有一个归属感,并且能让C++编译器兼容以前用C语言开发出来的项目。

在编写C++代码时,我强烈建议使用 class 来定义类,而使用 struct 来定义结构体,这样做语义更加明确。

使用 struct 来定义类的一个反面教材:

#include <iostream>
using namespace std;

struct Student{
    Student(char *name, int age, float score);
    void show();

    char *m_name;
    int m_age;
    float m_score;
};

Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(){
    cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}

int main(){
    Student stu("小明", 15, 92.5f);
    stu.show();
    Student *pstu = new Student("李华", 16, 96);
    pstu -> show();

    return 0;
}

运行结果:
小明的年龄是15,成绩是92.5
李华的年龄是16,成绩是96

这段代码可以通过编译,说明 struct 默认的成员都是 public 属性的,否则不能通过对象访问成员函数。如果将 struct 关键字替换为 class,那么就会编译报错。

参考资料

C++ class和struct到底有什么区别

  • 18
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老狼IT工作室

你的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值