C/C++编程:类

2023-11-15

什么是类

  • 类是一种用户定义(数据)类型。,类似与C语言的结构体
  • 无论是什么编程语言,进行面向对象程序设计都是从类的设计开始的。类则是C++面向对象编程的实现方式

类的声明与定义

语法:在这里插入图片描述
类关键词class、struct、union 之一
类可拥有下列种类的成员

  1. 数据成员
    a) 非静态数据成员,包括位域。
    b) 静态数据成员
  2. 成员函数
    a) 非静态成员函数
    b) 静态成员函数
  3. 嵌套类型

一些成员函数是特殊的:某些条件下,即使用户不定义,编译器也会定义它们。


类的声明和定义

我们来看个例子,首先声明一个student类

class student
{
    //可以在此处声明类成员变量和成员函数: 用于描述student的各方面特性,例如姓名、学号、年龄等信息。
};

声明了student数据类型之后,我们就可以用其定义变量了(在定义类的对象时,class关键字可要可不要,如下,但通常出于习惯我们通常都会省略掉class关键字),如:

// 定义单个变量
student LiLei;  //创建student类的对象。
class student LiLei; //同样正确
// 定义一个数组或者指针
student all_student[1000];
student * pointer;

在用类定义对象的时候,一定要先给出类声明,这就好比用某种自定义数据类型来定义变量的时候,我们必须要先给出该数据类型的声明一样。由于C++里面本身集成一些常用数据类型,如int、bool、double等,所以在用这些数据类型声明变量时不需要再由我们自己给出类型声明了。

类中的成员变量与成员函数

类是一种数据类型,该类型类似于普通的数据类型,但是又有别于普通的数据类型。类这种数据类型是一个包含成员变量和成员函数的一个集合。类中成分可以分为四种

静态数据成员

语法:

static 数据成员	

说明:

  • 是类的一部分但不是某个类对象的一部分的变量称为static成员。static成员只有唯一副本,而不像非static成员那样每个对象都有其副本
  • 静态数据成员不关联到任何对象。即使不定义类的任何对象它们也存在。也就是说,类的所有对象都有权访问它的同一副本
  • 整个程序只有一个拥有静态存储期(static)的静态数据成员实例,除非使用关键词 thread_local,该情况下每个线程都有一个具有线程存储期的该对象。
  • 静态数据成员不能为 mutable。
  • (C++17 起),静态数据成员可以声明为 inline
struct X
{
    inline static int n = 1;
};

非静态数据成员

  • 不允许使用 externregister(不建议使用,C++17起已经被弃用) 存储类说明符;
  • 不允许使用 thread_local 存储类说明符(但允许 static 数据成员);
#include <string>
class S
{
    int n;                // 非静态数据成员
    int& r;               // 引用类型的非静态数据成员
    int a[2] = {1, 2};    // 带默认成员初始化器的非静态数据成员 (C++11)
    std::string s, *ps;   // 两个非静态数据成员
    struct NestedS {
        std::string s;
    } d5;                 // 具有嵌套类型的非静态数据成员
    char bit : 2;         // 2 位的位域
};

静态成员函数

语法:
在这里插入图片描述
说明:

  • 静态成员函数不关联到任何对象。调用时,它们无 this 指针。
  • 它只能访问类的静态数据成员
  • 静态成员函数不能为 virtual、const 或 volatile。
  • 静态成员函数的地址可以存储在常规的函数指针中,但不能存储于成员函数指针中。
  • 需要访问类成员而不需要通过特定对象调用的函数叫做static成员函数
class Date{
	int d, m, y;
	static Date default_date;
public:
	Date(int dd = 0, int mm = 0, int yy = 0);
	static void set_default(int dd, int mm, int yy);
};

Date::Date(int dd, int mm, int yy){
	d = dd ? dd : default_date.d;
	m = mm ? mm : default_date.m;
	y = yy ? yy : default_date.y;
}

使用set_default(),可以在恰当的时候改变默认值。

可以像引用任何其他成员一样引用static成员。此外,不必提及任何对象即可引用static成员,方法是使用其类的名字作为限定,比如:

void f(){
	Date::set_default(4, 5, 1995);
}

如果使用了 static函数或者静态成员(没有使用就不必定义),我们就必须在某处定义它们。在static成员的定义中不必重复关键字static

Date Date::default_date {16, 1, 1995};
void Date::set_default(int dd, int mm, int yy){
    default_date  = {dd, mm, yy};
}

注意,Date{}表示Date::default_date 的值

Date copy_of_default_copy = Date{};

void f(Date);
void g(){
	f(Date{});
}

因此,我们不需要一个独立的函数来读取默认值。而且,当模板类型为Date无疑时,更简单的{}就足够了:

void f1(Date);

void f2(Date);
void f2(int);

void g(){
	f1({});  //ok:等价于f1(Date{});
	f2({}) ; //error: 二义性,f2(int)还是f2(Date)
	f2(Date{});
}

在多线程代码中,static数据成员需要某种锁机制或访问规则来避免竞争条件。

非静态成员函数

  • 非静态成员函数是声明于类的成员说明中,不带 static 或 friend 说明符的函数。
class S {
    int mf1(); // 非静态成员函数声明
    void mf2() volatile, mf3() &&; // 可为 cv 限定或引用限定
    int mf4() const { return data; } // 可内联定义
    virtual void mf5() final; // 可为虚函数,可使用 final/override
    S() : data(12) {} // 构造函数亦是成员函数
    int data;
};
int S::mf1() { return 7; } // 若不内联定义,则必须定义于命名空间

成员初始化

从C++11起,非静态成员声明符可以包含初始值设定项:

class CanInit
{
public:
    long num {7};       // OK in C++11
    int k = 9;          // OK in C++11
    static int i = 9; // Error: must be defined and initialized
                      // outside of class declaration.

    // initializes num to 7 and k to 9
    CanInit(){}

    // overwrites original initialized value of num:
    CanInit(int val) : num(val) {}
};
int main()
{
}

如果该构造函数对一个成员分配了一个值,则该值将覆盖声明时用于初始化该成员的值。

对于给定类类型的所有对象,只有一个静态数据成员的共享副本。必须在文件范围内定义静态数据成员并可在此范围内将其初始化

// class_members2.cpp
class CanInit2
{
public:
    CanInit2() {} // Initializes num to 7 when new objects of type
                 //  CanInit are created.
    long     num {7};
    static int i;
    static int j;
};

// At file scope:

// i is defined at file scope and initialized to 15.
// The initializer is evaluated in the scope of CanInit.
int CanInit2::i = 15;

// The right side of the initializer is in the scope
// of the object being initialized
int CanInit2::j = i;

类内初始化和成员初始化不是一回事

局部类

类声明可以出现在函数体内,该情况下它定义局部类。这种类的名字只存在于函数作用域中,且无法在函数外访问。

  • 局部类不能拥有静态数据成员
  • 局部类的成员函数无连接
  • 局部类的成员函数必须完全在类体内定义
  • 除闭包类型以外的 (C++14 起)局部类不能拥有成员模板
  • 局部类不能拥有友元模板
  • 局部类不能在类定义内定义友元函数
  • 函数(包括成员函数)内的局部类可以访问其外围函数能访问的相同名字。
  • 局部类不能用作模板实参
    (C++11 前)
#include <vector>
#include <algorithm>
#include <iostream>
 
int main()
{
    std::vector<int> v{1,2,3};
    struct Local {
       bool operator()(int n, int m) {
           return n > m;
       }
    };
    std::sort(v.begin(), v.end(), Local()); // C++11 起
    for(int n: v) std::cout << n << ' ';
}

在这里插入图片描述

成员访问

  • 可以通过对类X的对象使用.访问X的成员
  • 可以通过对类X的对象的指针使用->访问X的成员
struct X{
	int m;
	void f();
};

void user(X x, X *px){
	x.m = 11;
	px->m = 1;
}
  • 在类内部访问成员不需要任何运算符:
void X::f(){
	m = 1;  //相当于this->m = 1;
}
  • 成员函数可以在一个成员声明前就引用他:
struct X{
	void f() {return x};
	int m;
};
  • 如果我们希望引用一个类的公共成员,而不是某个特定对象的成员,应该使用类名::xxx限定方式:
struct X{
	int m;
	int f();
	static int sm;
};

int X::f() {return m};
X::sm{7};
int (X::)pmf() {&S::f};

建议

  • 将概念表示为类
  • 将类的实现与接口分类
  • 定义构造函数来处理对象初始化
  • 默认将单参数构造函数声明为explicit
  • 将不修改其对象状态(值)的成员函数声明为const成员函数
  • 具体类型是最简单的类。只要适用,就应该优先选择具体类型而不是更复杂的类或者普通数据结构
  • 仅当函数需要直接访问类的表示时才将其声明为成员函数
  • 使用名字空间建立类与其辅助函数间的显式关联
  • 如果一个函数需要访问类的表示,但是不需要使用某个具体对象来调用,建议将其实现为static成员函数*
    http://www.weixueyuan.net/view/6333.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C/C++编程:类 的相关文章

随机推荐

  • 问题:your cpu does not support kvm extensions

    问题 我的BIOS开启了CPU虚拟化 但是虚拟机仍然显示your cpu does not support kvm extensions 解决 1 关闭虚拟机 2 虚拟机上单击右键 设置 3 选择下图选项 4 重启虚拟机 问题解决
  • JAVA 中的 -> 是什么意思?

    在 JAVA核心编程 中 有一段这样的代码 import javax swing import java awt import java io File public class ImageViewer public static void
  • 我的创作纪念日2023.8.5

    机缘 在CSDN的创作开始于去年 创作的初衷是希望对自己的学习经历进行记录 同时也把自己的经验和收获传递给更多需要的小伙伴 创作博客的过程是一个将输入的知识进行再生产的过程 在此期间 知识获得了沉淀和提纯 思路和想法也愈发通畅 收获 1 在
  • sql根据入职日期查询工龄

    员工表 查询入职满5年的员工 员工表 查询入职满5年的员工在这里插入图片描述 部门表 在这里插入图片描述 SELECT FROM COM WHERE entry lt DATE SUB SYSDATE INTERVAL 5 YEAR 原文链
  • 苹果开发者账号Apple ID如何进行资料修改?

    我们在申请了开发者账号后 有时候需要对账号进行资料修改 只要你有了Apple ID 也就是邮箱 和苹果的密保 密码 那这个Apple ID就唯一属于你的了 下面会截图说明如何进行修改 首先登陆Apple ID管理网站 https apple
  • Leetcode466.统计重复个数——掐头去尾寻找循环点

    文章目录 引入 本题题解 引入 每日一题出现了这么一道题 466 统计重复个数 题目在此就不做展示了 直接说思路 刚拿到这道题的时候 首先会找 多少个s1才能够拼成一个s2 比如 abba 和 ab 那么一个 abba 里面就包含了 abb
  • 蓝桥杯真题:乘积尾零(2018 年省赛)

    如下的 1010 行数据 每行有 1010 个整数 请你求出它们的乘积的末尾有多少个零 5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6113 5659 5245 7432
  • c结构体中char[0]的作用-实现数组扩展

    struct Data int len char data 0 原来的data中没有元素 不分配内存 结构体Data的大小为4 假如现在分配15字节的内存 并且将指向这块内存的指针强制转换为 Data Data pData Data mal
  • 用于多模态图像配准的弱监督卷积神经网络

    Weakly Supervised Convolutional Neural Networks for Multimodal Image Registration 摘要 在多模态图像配准的监督学习中 最基本的挑战之一是体素级空间对应的基值的
  • lua学习笔记之详解lua堆栈

    原文连接 http blog csdn net musicvs article details 8440707 1 Lua的堆栈和全局表 我们来简单解释一下Lua的堆栈和全局表 堆栈大家应该会比较熟悉 它主要是用来让C 和Lua通信的 是的
  • STA series --- 8.Timing Verification (PARTI)

    本篇内容 基于阅读J Bhasker Rakesh Chadha著作 Static Timing Analysis for Nanometer Designs 后进行的总结以及自己的观点和感想 如有不正确的地方 还请指点 读者有微电子基础将
  • Web安全之SQL注入攻击

    什么是SQL注入式攻击 所谓SQL注入式攻击 就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串 欺骗服务器执行恶意的SQL命令 在某些表单中 用户输入的内容直接用来构造 或者影响 动态SQL命令 或作为存储过程的输入参数
  • Synchronized的原理及自旋锁,偏向锁,轻量级锁,重量级锁的区别

    在多线程并发编程中Synchronized一直是元老级角色 很多人都会称呼它为重量级锁 但是随着Java SE1 6对Synchronized进行了各种优化之后 有些情况下它并不那么重了 Java SE1 6中为了减少获得锁和释放锁带来的性
  • WebGoatV8.1(challenges)详细过关教程

    一 Admin lost password 设置代理继续抓包 刷新题目本页面 抓取url路径为 WebGoat challenge logo的包 重放在回应包里面搜索admin找到账号和密码 登录拿到flag 二 Without passw
  • 华为od统一考试B卷【师徒关系】

    题目描述 给定数组 2 1 3 2 每组表示师徒关系 第一个元素是第二个元素的老师 数字代表排名 现在找出比自己强的徒弟 输入 2 1 3 2 输出 0 1 2 第一行数据 2 1 表示排名第 2 的员工是排名第 1 员工的导师 后面的数据
  • Flask 数据库-单表操作

    Flask SQLAlchemy Flask SQLAlchemy是在Flask中操作关系型数据库的拓展 是以面向模型对象的形式操作数据库 通过迁移完成建表 安装 pip install flask sqlalchemy 基本配置 第一种
  • c语言2进制转3进制

    保存答案的 要求二进制满足最多64位 网上的答案都不对 听同学讲用了 unsigned long long 和 运算左移 方法一 include
  • Nodejs等待一段时间

    定义 function timeout ms return new Promise resolve reject gt setTimeout resolve ms done 使用 等待2秒 timeout 2000 then gt 这里写等
  • Auto.js监测抖音验证弹窗和关闭权限弹窗如(点击文字弹窗、滑动拼图解锁弹窗、上滑查看更多视频弹窗等)

    文章目录 前言 一 实现原理 二 使用步骤 1 代码示例 2 echo log方法 总结 前言 在使用Auto js实现抖音模拟点击过程中 会出现权限申请弹窗 验证弹窗 上滑查看更多视频弹窗等 阻塞脚本运行 下面给大家介绍下摸索的成果 一
  • C/C++编程:类

    什么是类 类是一种用户定义 数据 类型 类似与C语言的结构体 无论是什么编程语言 进行面向对象程序设计都是从类的设计开始的 类则是C 面向对象编程的实现方式 类的声明与定义 语法 类关键词 class struct union 之一 类可拥