C++类的学习(基础篇)

类是C++中的自定义类型,结合数据成员和成员函数。类包含private和public访问控制,用于封装数据。构造函数用于初始化对象,析构函数在对象销毁时执行清理工作。成员函数包括内联函数、const成员函数,如get_average()和show()。this指针允许在成员函数中引用当前对象。
摘要由CSDN通过智能技术生成

  • 类是一种自定义类型,类似于结构体。
  • 类将数据表示和操纵数据的方法组合成一个整洁的包。

类的组成

  • 类声明:以数据成员的方式描述数据部分,以成员函数(被称为方法)的方式描述公有接口。
  • 类方法定义:描述如何实现类成员函数。

类声明

class Student   // 关键字class标识类定义
{
    // 默认是私有的
        int m_math;     // 私有成员
    private:    // 私有成员
        std::string m_name;     // 成员变量
        int m_English;
        int m_Chinese;
        int m_sum;
        void set_sum()          // 内联方法
        {
            m_sum = m_math + m_English + m_Chinese;
        }
    public:     // 公有成员
        Student();      // 默认构造函数
        Student(std::string name)  // 构造函数
        {
            m_name = name;
        }
        Student(std::string name, int math, int English, int Chinese);   // 构造函数
        void set_scores(int math, int English, int Chinese);    // 公有成员函数
        double get_average() const;     // const成员函数
        void show() const;      // const成员函数
        ~Student();     // 析构函数
};

说明

  1. 关键字class表示类定义。
  2. 访问控制: 关键字private和public描述了对类成员的访问控制
    • public: 使用类对象的程序可以直接访问公有部分数据
    • private: 只能通过公有成员函数或者友元函数来访问私有部分数据
  3. 可以不必在类声明中使用关键字private,因为类对象的默认访问控制是private。

实现类成员函数

  • 定义成员函数时,使用作用域解析运算符::来标识函数所属的类。
  • 类方法可以访问类的private成员
Student::Student()
{
    m_name = "";
    m_math = 0;
    m_Chinese = 0;
    m_English = 0;
    m_sum = 0;
}

Student::Student(std::string name, int math, int English, int Chinese)
{
    m_name = name;
    set_scores(math,English,Chinese);
}

void Student::set_scores(int math, int English, int Chinese)
{
    m_math = math;
    m_English = English;
    m_Chinese = Chinese;
    set_sum();      // 调用私有方法
}

double Student::get_average() const
{
    return (double)m_sum / 3;
}
void Student::show() const
{
    std::cout << "name: " << m_name << std::endl;
    std::cout << "math: " << m_math << std::endl;
    std::cout << "English: " << m_English << std::endl;
    std::cout << "Chinese: " << m_Chinese << std::endl;
    std::cout << "Sum: " << m_sum << std::endl;
}
Student::~Student()
{
    std::cout << "This is destructor!" << std::endl;
}

内联方法

定义位于类声明中的函数都将自动成为内联函数,所以set_sum()是一个内联函数。

如果想在类声明外定义成员函数为内联函数,只要在函数定义时使用inline限定符即可。

class Student
{
    private:
        ...
        void set_sum();
        ...
};
inline void Student::set_sum()
{
    m_sum = m_math + m_English + m_Chinese;
}

类的构造函数和析构函数

构造函数专门用于构造新对象、将值赋给他们的数据成员(做初始化工作)。

默认构造函数

类设计时如果没有提供任何构造函数,C++会自动提供一个默认构造函数。它是默认构造函数的隐式版本,不做任何工作。

类似于int a 创建了a但没有赋值。

Student::Student()
{
    
}

注意

只有当没有定义任何构造函数时,编译器才会提供默认构造函数。如果提供了构造函数,但是没有提供默认构造函数,则下面声明会报错

Student stu1;   // 没有默认构造函数

可以自己提供一个默认构造函数,给成员变量赋初值

Student::Student()
{
    m_name = "";
    m_math = 0;
    m_Chinese = 0;
    m_English = 0;
    m_sum = 0;
}

析构函数

用构造函数创建对象,对象过期时,程序会自动调用析构函数,用来完成清理工作。(做清理工作)

析构函数的名称是在类名前加上~

Student::~Student()
{
    std::cout << "This is destructor!" << std::endl;
}

如果程序员没有提供析构函数,C++会隐式地声明一个默认析构函数。

Student::~Student()
{
    
}

如果使用了new创建成员变量,必须在析构函数中使用delete释放掉该成员变量。

Student~Student()
{
    delete var;
}

析构函数何时被调用

  1. 如果创建的是静态存储类对象,则其析构函数将在程序结束时自动被调用。
  2. 如果创建的是自动存储类对象,则其析构函数将在执行完代码块时自动被调用。
  3. 如果对象是通过new创建的,当使用delete来释放内存时,其析构函数将自动被调用。

const成员函数

为了确保调用成员函数时,调用对象不被修改,可以将成员函数声明为const成员函数,在声明时,在函数后面加上const关键字。

// 声明
void show() const;

// 定义
void Student::show() const
{
    ...
}

使用类

使用对象的成员函数,和使用结构体成员一样,通过成员运算符.->

int main()
{
    Student stu1;   // 默认构造函数
    stu1.show();    // 调用公有成员函数
    Student stu2("zhangsan");
    stu2.set_scores(90,98,88);
    std::cout << stu2.get_average() << std::endl;
    stu2.show();
    Student stu3("lisi", 89,85,94);
    stu3.show();

    Student *stu4 = new Student;
    stu4->show();

    Student *stu5 = new Student("wangwu", 90,90,90);
    stu5->show();
    delete stu4;
    delete stu5;
}

this指针

每一个类对象中都有一个this指针指向本对象。比如在给成员变量赋值时使用this指针

Student::Student(std::string name, int math, int English, int Chinese)
{
    this->m_name = name;
    this->set_scores(math,English,Chinese);
}

使用this指针实例

比较两个学生的平均数,并返回高分数的学生

class Student
{
    ...
    public:
        const Student &topval(const Student &) const;
    ...
}

const Student & Student::topval(const Student &stu) const
{
    if(this->get_average() > stu.get_average())
    {
        return *this;		// 返回本对象
    }
    else
    {
        return stu;
    }
}

int main()
{
    Student stu2("zhangsan");
    stu2.set_scores(90,98,88);
    std::cout << stu2.get_average() << std::endl;
    stu2.show();
    Student stu3("lisi", 89,85,94);
    stu3.show();
    Student stu6 = stu2.topval(stu3);   // 比较stu2和stu3的成绩
    stu6.show();
}

整体代码

#include <iostream>
#include <string>

using namespace std;

class Student   // 关键字class标识类定义
{
    // 默认是私有的
        int m_math;     // 私有成员
    private:    // 私有成员
        std::string m_name;     // 成员变量
        int m_English;
        int m_Chinese;
        int m_sum;
        void set_sum()          // 内联方法
        {
            m_sum = m_math + m_English + m_Chinese;
        }
    public:     // 公有成员
        Student();      // 默认构造函数
        Student(std::string name)  // 构造函数
        {
            m_name = name;
            m_English = 0;
            m_Chinese = 0;
            m_math = 0;
            set_sum();
        }
        Student(std::string name, int math, int English, int Chinese);   // 构造函数
        void set_scores(int math, int English, int Chinese);    // 公有成员函数
        double get_average() const;
        void show() const;
        const Student &topval(const Student &) const;
        ~Student();   // 析构函数
};

int main()
{
    Student stu1;   // 默认构造函数
    stu1.show();    // 调用公有成员函数
    Student stu2("zhangsan");
    stu2.set_scores(90,98,88);
    std::cout << stu2.get_average() << std::endl;
    stu2.show();
    Student stu3("lisi", 89,85,94);
    stu3.show();

    Student stu6 = stu2.topval(stu3);
    cout << "higher scores" << endl;
    stu6.show();
    cout << endl;
    Student *stu4 = new Student;
    stu4->show();

    Student *stu5 = new Student("wangwu", 90,90,90);
    stu5->show();
    delete stu4;
    delete stu5;
}
const Student & Student::topval(const Student &stu) const
{
    if(this->get_average() > stu.get_average())
    {
        return *this;
    }
    else
    {
        return stu;
    }
}
Student::Student()
{
    m_name = "";
    m_math = 0;
    m_Chinese = 0;
    m_English = 0;
    m_sum = 0;
}

Student::Student(std::string name, int math, int English, int Chinese)
{
    this->m_name = name;
    this->set_scores(math,English,Chinese);
}

void Student::set_scores(int math, int English, int Chinese)
{
    m_math = math;
    m_English = English;
    m_Chinese = Chinese;
    set_sum();      // 调用私有方法
}

double Student::get_average() const
{
    return (double)m_sum / 3;
}
void Student::show() const
{
    std::cout << "name: " << m_name << std::endl;
    std::cout << "math: " << m_math << std::endl;
    std::cout << "English: " << m_English << std::endl;
    std::cout << "Chinese: " << m_Chinese << std::endl;
    std::cout << "Sum: " << m_sum << std::endl;
}
Student::~Student()
{
    std::cout << "This is destructor!" << std::endl;
}

作用域为类的常量

在类中定义常量,并使用这个常量定义一个数组

错误的写法

class Person
{
    private:
        const int size = 30; 
        char m_name[size];		// 错误
};

这样会报错,因为声明类只是描述了对象的形式,并没有创建对象。因此,在创建对象前,将没有用于存储值的空间。

可行的方法

  1. 方法一,在类中声明一个枚举

在类声明中声明的枚举的作用域为整个类,因此可以用枚举为整型常量提供作用域为整个类的符号名称。

class Person
{
    private:
        enum {size = 30;};
        char m_name[size];
};

用这种方式声明枚举并不会创建类数据成员。也就是说,所有对象中都不包括枚举。size只是一个符号枚举,在作用域为整个类的代码中遇到它时,编译器将用30来替换它。类似于宏定义。

  1. 方法二,使用关键字static
class Person
{
    private:
        static const int size = 30;
        cahr m_name[size];
};

这样声明的常量将与其他静态变量存储在一起,而不是存储在对象中。

实例

#include <iostream>
#include <cstring>
using namespace std;

class Person
{
	private:
		static const int size = 30;
		// enum { size = 30 };
		char m_name[size];
	public:
		Person();
		Person(const char *name);
		friend ostream &operator<<(ostream &os, const Person& p);
};
int main()
{
	Person p1("zhangsan");
	cout << p1 << endl;
	return 0;
}

Person::Person()
{
	m_name[0] = '\0';
}
Person::Person(const char *name)
{
	strncpy(m_name, name, size - 1);
}

ostream &operator<<(ostream &os, const Person& p)
{
	os << p.m_name;
	return os;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值