首页 > 编程语言 >C++学习笔记1:类的使用

C++学习笔记1:类的使用

时间:2022-11-12 19:40:58浏览次数:40  
标签:函数 成员 笔记 学习 book 参数 C++ age 构造函数

C++学习笔记1:类的使用_构造函数

  • [基本数据结构]()
  • [类的使用]()
  • [类的继承和派生]()
  • [面向对象特征之一——多态]()
  • [操作符重载]()
  • [const关键字的使用]()

1. 类的定义与使用

1.1 类的定义

最简单的类的申明:

class Student{

};

在类的定义最后需要加上分号,这是和java不同的地方,否则会有编译错误。

1.2 类的使用

即创建类的实例——对象。在java中你会使用到​​new​​关键字,而在c++中,创建对象与使用普通的数据类型一样简单:

Student studentObject;

2. 类的成员变量和成员函数

2.1 成员变量

class Student
{
char name[20]; //姓名
int id_num; //学号
int age; //年龄
char sex; //性别

和java不同,类的成员变量不能在创建的时候初始化值。

2.2 成员函数

和java不同,c++的成员函数有两种定义方式:

1.类内部申明,类外定义(实现):

class student
{
void set_age(int a);
int get_age();
};
//在类外部定义set_age函数
void student::set_age(int a)
{
age = a;
}
//在类外部定义get_age函数
int student::get_age()
{
return age;
}

在类内部申明函数,在类的外部定义的时候通过作用域操作符 :: 进行实现。

申明的时候,只需写出返回类型、函数名称、参数列表、末尾分号即可,不能加上空的大括号。

    返回类型 类名::成员函数名(参数列表)
{
//函数体
}

你也可以在类的成员函数申明的前面加上​​inline​​关键字使其变成内联函数。内联函数可以优化程序的执行效率。

class student
{
inline void set_age(int a);
inline int get_age();
};
//在类外部定义set_age函数
void student::set_age(int a)
{
age = a;
}
//在类外部定义get_age函数
int student::get_age()
{
return age;
}

2. 类内部边申明边定义(实现)

class Student{
void set_age(int a){age = a;}
int get_age(){return age;}
}

这种方式其实和java的成员函数调用方式是相同的。

2.3 访问限制

和java的语法类似,c++也提供了三种关键字:

  • ​public​​:本类和其他类都可以访问到
  • ​private​​: 只有本类可以访问到
  • ​protected​​:只有本类和派生的类可以访问。

但是使用的语法格式有点不同。

class book
{
public:
void setprice(double a);
double getprice();
private:
double price;
};

通过这种格式,可以将属性为​​public​​的变量或函数申明在一起。避免了重复的写权限限制符号。

当然,权限相同的成员也可以分开声明,申明的顺序也是无所谓的。

2.4 访问成员变量/函数

创建的对象就是类的实例,就直接使用​​.​​点选择符,这里是和java一样的。

创建的如果是对象的指针,需要使用​​->​​箭头选择符访问成员。java中没有指针就没有这条规则。

#include <iostream>
using namespace std;
class book
{
public:
void setprice(double a);
double getprice();
private:
double price;
};
void book::setprice(double a)
{
price = a;
}
double book::getprice()
{
return price;
}
int main()
{
book Alice;
Alice.setprice(29.9);
cout<<"The price of Alice is $"<<Alice.getprice()<<endl;
book *Harry = new book;
Harry->setprice(49.9);
cout<<"The price of Harry is $"<<Harry->getprice()<<endl;
return 0;
}

注意:C++类class和结构体struct区别

class和struct都可以定义一个类的结构。

  • 采用struct关键字,结构体中定义的成员变量或成员函数默认都是public属性的。
  • 使用class关键字,类中定义的成员变量或成员函数默认都是private属性的,

除此之外,没有其他任何区别。

3. 构造函数

3.1 构造函数的定义

构造函数的声明与定义的方式与普通函数是相同的,也是有两种方式,但是有以下几点特殊地方:

  • 构造函数的函数名必须与类名相同;
  • 构造函数无返回值;
  • 当我们创建类对象的时候构造函数会被自动调用,而无需我们主动调用。

这三点和java中语法也是一样的。

通常如果在定义类的时候,没有定义任何一个构造函数的时候,系统会自动生成一个默认构造函数。默认构造函数就是不带任何参数的构造函数。其它带参数的构造函数统称为带参构造函数。

如果在类中声明了任何一个构造函数,则系统不会自动生成默认构造函数。

如果在创建对象时候表示使用哪个构造函数呢?只要在对象名称后加一对小括号,小括号类参数与对应的构造函数参数对应即可:


class book
{
public:
book(){}
book(char* a, double p);

private:
double price;
char[] title;
};

book::book(char[] a, double p)
{
title = a;
price = p;
}

int main()
{
book Harry("Harry Potter", 49.9);
return 0;
}

3.2 初始化参数表

除了通过在构造函数的函数体内进行成员变量的初始化,还可以通过在构造函数的后面以下面的格式初始化参数

构造函数(参数列表):成员变量1(初始值),成员变量2(初始值)……{}

举个例子:

class book
{
public:
book(){}
book(char *a, double p):title(a),price(p){}
};

对,你没有看错,还有这种类似函数的方式给成员变量赋值。

这种写法本质就是为了简写成员变量的赋值操作,你同样可以用普通的方式定义构造函数:


book(char *a, double p){
title = a;
price = p;
}

在java语法中,你可以在初始化块中给成员变量中赋值,很容易理解。
但是在c++中提供这样一种以成员变量名作为函数名,参数列表是变量的值的形式初始化成员变量。

值得注意的是:参数初始化顺序与初始化表列出表量的顺序无关,参数初始化顺序只与成员变量在类中声明的顺序有关

3.3 构造函数的参数默认值

PHP中的函数参数可以在调用之前就可以赋值一个默认值,因为PHP不支持函数的重载。通过这种方式,当你调用的函数时候没有给其他参数赋值,其他函数也会有一个默认值:

function exampleFunction($parm1,$parm2 = "world"){
echo $parm1 ." ". $parm2;
}

exampleFunction("hello")
//输出: hello world;

上面的代码可以很清楚的看到,第二个参数已经被赋值了默认值​​world​​,当你没有给定第二个参数的时候,第二个参数仍然是有值的。

c++的构造函数也支持参数默认赋值,比如:

class book
{
public:
book(){}
book(char* a, double p = 5.0);
private:
double price;
char * title;
};
book::book(char* a, double p) //在定义函数的时候可以不指定默认参数
{
title = a;
price = p;
}

此时,当我们这样创建对象的时候:

Book Time("Time book")

调用的就是第二个构造函数,并且​​price​​​自动赋值为默认值​​5.0​

但默认参数的构造函数会与某些构造函数重载冲突:

book(char* a);

如果我们再申明这样一个构造函数,之前创建对象就会发生编译错误,因为编译器不知道调用哪一个构造函数了。

换句话说,C++在支持构造函数的重载的条件下,基本上没必要使用带默认参数的构造函数

* 3.4 转型、拷贝构造函数

3.4.1 转型构造函数

构造函数关于是否有参数可以分为:

  • 不带参数构造函数
  • 带参数构造函数(含带默认参数的构造函数)

其中带参数构造函数中有两种特殊的构造函数:

  • 转型构造函数
  • 拷贝构造函数

转型构造函数和普通的构造函数没啥区别,就是参数列表只有一个参数,创建对象的时候如果调用该构造函数,就是意味着将参数转换为了一个类的对象,这没什么特别的。

特别之处在于这里有一个隐式的类型转换:比如你创建一个字符串变量,但是你将该变量传入了一个参数为类对象的函数,这个时候就会自动的发生字符串到类对象的隐式对象类型转换

class student
{
public:
student(char * n){name = n;}//转型构造函数
private :
char * name;
}


void fun(Student studentObj){};

char * name = “Harry Potter”;
fun(name);

这个时候字符串name自动转换为student类的对象,转换的过程中自动调用转型构造函数。

隐式转换会带来调试的困难,可以在构造函数前加上​​explict​​关键字,避免这种自动转换。

换句话说,转型构造函数就是参数只有一个的一类构造函数,能实现将参数转换为类对象的功能。

3.4.3 拷贝构造函数

4. 析构函数

在Java中无需自行设计析构函数,java有一套系统级的垃圾回收管理程序。

在创建对象的时候系统会自动调用构造函数,在对象需要被销毁的时候,系统也会自动调用析构函数。

与构造函数类似,析构函数也是一个成员函数,但是有如下特殊之处:

  • 无返回值
  • 没有参数,不能被重载,因此一个类也只能含有一个析构函数
  • 函数名必须为“~类名”的形式,符号“~”与类名之间可以有空格

5. 类的高级用法

5.1 常量指针this

与java类似,在类的每个成员函数中包含一个常量指针,该指针指向调用该函数的对象。

与java类似,该指针只要是用来区分同名的成员变量与参数名称的:

void setprice(double price)
{
price = price;
}

5.2 new和delete操作符

c++创建对象有两种方式,一种就是普通的直接通过​​类名 对象名(构造函数参数列表)​​ 创建,另一种就是通过​​new​​关键字创建。

两种方式创建对象的空间分配方式有分别。

  • 第一种空间分配在栈中,由系统可以直接管理,比如在代码块外,块内的对象就会被清理。
  • 第二种的空间分配在堆上,大小可以很大, 但是销毁得由程序本身处理。

使用 ​​new​​ 关键字会自动调用构造函数
使用 ​​delete​​ 关键字会自动调用析构函数

5.3 const关键字

const表示一些不希望被人们修改的数据,与java语法中的​​final static​​ 有类似之处,但是也有很多区别。

const关键字可以定义在成员变量、成员函、对象、对象的常引用上。

5.3.1 修饰(成员)变量

这个很好理解,在变量最前面加上关键字表示初始化之后禁止二次修改。const成员变量的初始化只能通过参数初始化表进行初始化

 const int a=5;

5.3.2 修饰成员函数

const成员函数可以使用类中的所有成员变量,但是不能修改任何成员变量,也不能调用类中任何非const成员函数

fun(形参) const{}

5.3.3 修饰类对象

用const修饰的类对象,该对象内的任何成员变量都不能被修改。

因此不能调用该对象的任何非const成员函数,因为对非const成员函数的调用会有修改成员变量的企图。

class A
{
public:
void funcA() {}
void funcB() const {}
};

int main
{
const A a;
a.funcB(); // 可以
a.funcA(); // 错误

const A* b = new A();
b->funcB(); // 可以
b->funcA(); // 错误
}

5.3.4 修饰类对象的引用

我们在有些函数参数中会使用到对象,这个时候我们不是直接将对象做为参数,而是使用对象的引用。

此时我们在对象的引用前加上关键字,避免函数对对象本身做出任何修改:

void display(const book &b)
{
b.setprice(59.9); //compile error
cout<<"The price of "<<b.gettitle()<<" is $"<<b.getprice()<<endl; //ok
}

5.4 static关键字

好了,这个关键字可以说是和java一致的了。

5.4.1 静态成员变量

该变量是同步于类的所有对象,也就是类的变量

5.4.2 静态成员函数

5.5 友元函数和友元类

5.5.1 友元函数

我们知道对象是无法直接调用私有变量或者私有函数的,只有在类中的函数才可以使用类的私有变量或者私有函数。

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,其格式如下:

friend  返回类型 函数名(形式参数);
  • 友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。
  • 一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
  • 友元函数的调用与一般函数的调用方式和原理一致。

5.5.2 友元类

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。

当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:

friend class 类名;

当你在一个类中申明另一个类为该类的友元的时候,表明该友元类的所有成员函数都可以使用该类的所有信息。这种顺序是单向的。

其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

例如,以下语句说明类B是类A的友元类:

      class A
{

public:
friend class B;

};

经过以上说明后,类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员。

使用友元类时注意

  • 友元关系不能被继承。
  • 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
  • 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明。

标签:函数,成员,笔记,学习,book,参数,C++,age,构造函数
From: https://blog.51cto.com/u_15870498/5846743

相关文章

  • 机器学习模型监控清单
    一旦在生产环境中部署了机器学习模型,就需要确保它的性能。在本文中,我们建议如何监视您的模型和要使用的开源工具。建立机器学习模型并不容易。在生产环境中部署服务更加困难......
  • 梦笔记1107
    验证朱的皇帝身份?找到什么刀,宝珠?朱与妃子逗乐,旁边一伙小姑娘在看。我对身边的那个说,各有福报。她说羡慕长发,我说你的也不错。半路有人截,我先带着跑路了,到了个厕所。地上拣到......
  • 20221410 《计算机基础与程序设计》第十一周学习总结
    作业信息|这个作业属于哪个课程|<班级的链接>(https://edu.cnblogs.com/campus/besti/2022-2023-1-CFAP))||这个作业要求在哪里|<作业要求的链接>(https://edu.cnblogs.co......
  • 设计模式学习(二十三):中介模式
    设计模式学习(二十三):中介模式作者:Grey原文地址:博客园:设计模式学习(二十三):中介模式CSDN:设计模式学习(二十三):中介模式中介模式中介模式是一种行为型模式。举个简单的例子......
  • 2022-2023-1 20221307-计算机基础与程序设计 第十一周学习总结
    作业信息班级链接:https://edu.cnblogs.com/campus/besti/2022-2023-1-CFAP作业要求:https://www.cnblogs.com/rocedu/p/9577842.html#WEEK11作业目标:学习《C语言程序设计》......
  • 联通DataOps和MLOps:将机器学习推理作为新的数据源
    【编者按:随着大数据和AI的关注重点转向工程化和能效,DataOps和MLOps逐渐兴起。DataOps侧重于提高数据分析质量、缩短数据交付周期,MLOps侧重于快速交付AI模型。数据是AI开发生......
  • 双11,用Python爬取4000多条笔记本电脑的销售数据并分析
    双11,用Python爬取4000多条笔记本电脑的销售数据并分析2022年,大部分电子产品的销量都在下滑,比如手机,一方面,产品的创新和提升不足,另一方面,大部分人更愿意把钱存起来,降低生活中......
  • Oracle 19C学习 - 20. 临时表
    临时表是什么临时表是用来暂时保存临时数据的一个数据库对象。它只能保存在临时表空间,而无法保存在用户表空间。Oracle中,临时表分为SESSION会话和TRANSACTION事务两种。......
  • 深入浅出学习透析Nginx服务器的基本原理和配置指南「初级实践篇」
    什么是Nginx?Nginx(EngineX)是一个轻量级的Web服务器、反向代理服务器及电子邮件(IMAP/POP3)代理服务器、高性能的HTTP服务器,它以高稳定性、丰富的功能集、示例配置文件和......
  • 详解数据预处理和特征工程-特征选择-Embedded嵌入法【菜菜的sklearn课堂笔记】
    视频作者:[菜菜TsaiTsai]链接:[【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili]嵌入法是一种让算法自己决定使用哪些特征的方法,即特征选择和......