C++(八)类


C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。

面向对象的重要特性:
抽象:类就是对象的抽象,而对象就是类的具体表现形式。
封装和数据隐藏:对象中的函数名就是对象的对外接口,函数的内部实现别人没必要知道。比如手机对象,你打电话只需要拨号可以了。没必要手机对象是怎么发送信号的,对方的语音信息怎么接收过来,怎么转成音频接收的。这就是对象的封装与信息屏蔽。
多态:对同一类别的不同对象调用同一个行为或者函数的时候,表现不同。比如狗对象:调用狗叫的方法,各品种狗的叫声都不尽相同。
继承:就是在以前类型的基础上进行了继承与重用。比如:学生类,小学生有语文数学两科目,中学生除了继承小学生的科目外,还有英语、生物、化学、历史、地理、物理等。
代码的可重用性

类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。

一、类

在C++中对象的类型称为类(class),用来表示一类具有共同属性和行为的类型。例如:人类,狗类,动物类,哺乳动物类等等。在C++中一般是先声明一个类类型,然后用这个类类型去定义多个对象,所以,对象就是类类型的一个实例,或者说是类类型的一个实例化的变量。

类类型是抽象出来的,所以类类型跟C++中的其他类型一样,不占用内存空间,而对象就是类类型的实例,是真正的变量,所以是占用存储空间的。

1.1 类类型的声明

简单的类类型的声明,从下方可以看出,结构体类型与类类型的声明的区别;其实只是将struct改成class。

// 声明一个结构体的类型如下
struct Student
{
    string name;
    int num;
    char sex;
    int age;
};

class Student
{
    string name;
    int num;
    char sex;
    int age;
};

在class中,我们称name,num,sex 叫做成员变量。

说明:struct 和 class 关键字的区别:
在C++中已经对struct进行了扩充,不仅可以声明成员变量,还可以声明成员函数,class关键字本身就是从struct发展而来的,所以struct支持的,class都支持。
最重要的一个区别就是:class默认的成员访问限定符是privatestruct默认的成员访问限定符是public。也就是说,我们无法访问上述类中Student.name。

1.2 成员访问限定符

C++针对类的成员,设定了三种方式的访问限定符:publicprivateprotected
在 class 中,public、private、protected 可以出现多次,也没有先后顺序之分。

public:意为共有的,公用的成员,既可以被本类中的成员函数引用,也可以被类的作用域的其他函数所引用,即从类的外部是可以调用的;

private:意为私有的成员,只能被本类的成员函数所引用,类外部不能调用(友元类可以),
例如,我家的房子就好比是一个类,卧室就是private类型的成员,是一个相对隐私的地方。如果来客人了,我不希望客人访问我的卧室,除非经过我的允许(让成员函数去访问);

protected:意为受保护的成员,不能被类外访问,这点类似private,但是可以被派生类的成员函数访问。

1.3 如何决定成员变量及成员函数的访问权限

一般情况下,如果不希望外界访问本类的成员变量,那么就可以把成员变量都声明为私有的。但是有个前提必须提供可以访问的接口函数,不然一个类的所有成员都是private私有的话就没有意义了。比如在Student这个类中,如果把sex性别这个成员变量设置为私有的,那么Student类就应该提供可以修改或者读取sex成员变量的成员函数,并且这个函数是public的,不然外界想要知道sex变量的值就没办法获取了。

当然,也可以把一些成员设置为私有的,但是不对外提供修改的接口,因为可能这个属性或者成员变量对于类对象来说可能不想被外面知道或者修改。比如:一家人,有一个睡觉磨牙,这个属性对别人有意义吗?家里人和自己知道就行,外界不需要知道。

还有一种情况就是将成员函数声明为私有的,这说明这个私有的成员函数只能被该类的其他成员函数所调用,是作为辅助的接口函数的,是在类的内部使用,不对外公开。

小案例:

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;


class Student
{
public:
	string name;
	int num;
	int age;

private:
	char sex;

public:
	char set_sex(char SEX)
	{
		char sex = SEX;
		return sex;
	}
};

int main() 
{
	Student stu01;
	stu01.name = "zhangsan";
	stu01.num = 10001;
	stu01.age = 12;
	cout << stu01.name << " ;" << stu01.num << " ;" << stu01.age << " ;" << stu01.set_sex('F') << endl;
	return 0;
}

==========运行输出=============
zhangsan ;10001 ;12 ;F

在上述案例中,通过类中的公有成员函数访问私有成员变量。

概念描述
类成员函数类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。
类访问修饰符类成员可以被定义为 public、private 或 protected。默认情况下是定义为 private。
构造函数 & 析构函数类的构造函数:在创建一个新的对象时自动被调用。
类的析构函数:在删除所创建的对象时自动被调用。
C++ 拷贝构造函数拷贝构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。
C++ 友元函数友元函数可以访问类的 private 和 protected 成员。
C++ 内联函数通过内联函数,编译器试图在调用函数的地方扩展函数体中的代码。
C++ 中的 this 指针每个对象都有一个特殊的指针 this,它指向对象本身。
C++ 中指向类的指针指向类的指针方式如同指向结构的指针。实际上,类可以看成是一个带有函数的结构。
C++ 类的静态成员类的数据成员和函数成员都可以被声明为静态的。

上述的拷贝构造函数需要避免可能的析构函数报错。

二、类的成员函数

2.1 类的普通成员函数:

类的普通成员函数跟普通的函数没什么太大的区别,唯一的区别就是必须由该类的实例化对象去调用。
类的静态成员函数

2.2 inline :内联函数

内联函数 是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。对内联函数进行任何修改,都需要重新编译函数的所有客户端。用inline关键字声明的函数,可以在调用的时候,将函数的代码直接嵌入到调用的地方,所以大大的减少了函数调用的开销,提高了效率。
关于更多【请点击】

class Student
{
public:
    string name;
    int num;
    int age;

private:
    char sex;
    inline int max_num(int x, int y)
    {
        return x > y ? x : y;
    }

public:
    int get_max_num(int a, int b, int c)
    {
        int max_ab = max_num(a, b);
        return max_ab > c ? max_ab : c;
    }

    void print_name()
    {
        cout << "name = " << name << endl;
    }
};

说明:默认情况下,在类体中直接定义/实现的函数,C++会自动的将其作为inline内联函数来处理,所以类似上面的代码:max_num、get_max_num、print_name 函数都会被看成是 inline 内联函数。而在类体外部定义的函数C++则会将其作为普通的类的成员函数来处理。

2.3 类的声明和成员函数分离

一般情况下,可以把类的声明和实现都写在一起,但是,随着类的功能越来越多,类中的成员变量和成员函数也是越来越多,类的代码长度就越来越大,而且随着长度的增加不太便于阅读,层次不清晰,让人一眼望过去就一大面。
好的做法就是将类的声明和成员函数的定义分离开,成员函数的声明放在类的内部实现或者定义放在类的外部,加上作用域限定一下就行。

类的声明:将其放到.h 头文件

class Student
{
public:
    string name;
    int num;
    int age;

private:
    char sex;
    int max_num(int x, int y);

public:
    int get_max_num(int a, int b, int c);
    void print_name();
};

类的成员函数的实现:将其放到 .cpp 文件中

int Student::max_num(int x, int y)
{
    return x > y ? x : y;
}

int Student::get_max_num(int a, int b, int c)
{
    int max_ab = max_num(a, b);
    return max_ab > c ? max_ab : c;
}

void Student::print_name()
{
    cout << "name = " << name << endl;
}

注意:成员函数需要添加类的作用域修饰:Student::,如上分离后可以在多个.cpp文件中访问该对象以及对象的成员函数(方法)。

2.4 类的静态成员

1、类的静态成员变量:
用类定义的多个对象之间彼此独立,各自拥有自己的一套成员变量,互不影响!但是有时候呢,某个类的所有对象共同拥有一个东西,或者说一个变量。
打个比方,咱们之前定义的学生类 CStudent,这个学校的每个学生都有自己的名字、学号、性别、年龄等属性。那么他们有没有共同的属性呢?有,比方说该学校的校长。这个校长不属于某个学生,而是属于这个学生类大家的,或者说属于这个学校。

所以,这时候将校长作为类的静态成员变量:
①、这样所有对象都可以直接访问这个静态成员变量,而且值是一样的;
②、静态成员变量在内存中只占用一份存储空间;
③、静态成员变量的值对于所有对象来说都是一样的。如果其中一个对象调用函数将其改变了,那么其他成员在访问这个静态成员变量的时候的值都是改变之后的;
④、只要在类中定义了类的静态成员变量,那么就占用存储空间了,不管有没有定义这个类的对象,因为静态成员变量不属于任何类对象,而是属于该类;
⑤、静态数据成员需要在类外进行声明或声明并初始化,否则在使用的时候会报链接的错误;
⑥、类的静态成员在定义的时候需要加 static,在类外声明的时候不需要加 static 关键字;
⑦、不能用构造函数的参数初始化表的形式对静态成员进行初始化操作;
⑧、静态数据成员既可以通过对象名引用,也可以通过类名来直接引用;
⑨、public 公有类型的静态数据成员,可以被类的对象引用,也可以直接用类名来引用。但如果静态数据成员被定义成private私有的,那么通过对象或者类名来引用都是不可以的,必须通过类的public类型的静态成员函数来引用了。

2、类的静态成员函数:
跟类的静态成员变量一样,类的静态成员函数也不属于该类的对象,而是属于这个类。
①、类的静态成员函数可以通过类对象调用,也可以通过类名调用;
②、类的普通成员函数中可以使用标识该类对象的this指针,但是类的静态成员函数是属于类,不属于任何对象,所以静态成员函数中没有this指针,也就无法访问本类的非静态成员变量,因为不知道是哪个对象的。
③、所以,类的静态成员函数可以直接引用类的静态成员变量,因为他们的作用域相同,都是属于该类的。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页