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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++学习笔记1:类的使用相关的知识,希望对你有一定的参考价值。

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

  • [基本数据结构]()
  • [类的使用]()
  • [类的继承和派生]()
  • [面向对象特征之一——多态]()
  • [操作符重载]()
  • [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的友元,同样要看类中是否有相应的申明。

以上是关于C++学习笔记1:类的使用的主要内容,如果未能解决你的问题,请参考以下文章

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

Swift学习笔记九:类 Class

Core java for impatient 笔记

swift学习笔记构造过程

C++ Primer 5th笔记(chap 18 大型程序工具) 多重继承与虚继承

寒假学习笔记