C++数据封装以及定义结构介绍
先介绍一个字符串比较函数:strcmp(s1,s2),当s1<s2时,返回一个负整数;当s1=s2时,返回值为0;当s1>s2时,返回一个正整数
还有一个字符串复制函数:strcpy(a,b),表示将字符串b的值复制给字符串a当然字符串b的长度不能超过字符串a
定义结构
为了定义结构,您必须使用 struct 语句。struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:
struct type_name {member_type1 member_name1;member_type2 member_name2;member_type3 member_name3;..} object_names;
type_name 是结构体类型的名称,member_type1 member_name1 是标准的变量定义,比如 int i; 或者 float f; 或者其他有效的变量定义。在结构定义的末尾,最后一个分号之前,您可以指定一个或多个结构变量,这是可选的。下面是声明一个结构体类型 Books,变量为 book:
struct Books{ char title[50]; char author[50]; char subject[100]; int book_id;} book;
访问结构成员
为了访问结构的成员,我们使用成员访问运算符(.)。成员访问运算符是结构变量名称和我们要访问的结构成员之间的一个句号。
下面的实例演示了结构的用法:
#include <iostream>#include <cstring> using namespace std; // 声明一个结构体类型 Books struct Books{ char title[50]; char author[50]; char subject[100]; int book_id;}; int main( ){ Books Book1; // 定义结构体类型 Books 的变量 Book1 Books Book2; // 定义结构体类型 Books 的变量 Book2 // Book1 详述 strcpy( Book1.title, "C++ 教程"); strcpy( Book1.author, "Runoob"); strcpy( Book1.subject, "编程语言"); Book1.book_id = 12345; // Book2 详述 strcpy( Book2.title, "CSS 教程"); strcpy( Book2.author, "Runoob"); strcpy( Book2.subject, "前端技术"); Book2.book_id = 1234556; // 输出 Book1 信息 cout << "第一本书标题 : " << Book1.title <<endl; cout << "第一本书作者 : " << Book1.author <<endl; cout << "第一本书类目 : " << Book1.subject <<endl; cout << "第一本书 ID : " << Book1.book_id <<endl; // 输出 Book2 信息 cout << "第二本书标题 : " << Book2.title <<endl; cout << "第二本书作者 : " << Book2.author <<endl; cout << "第二本书类目 : " << Book2.subject <<endl; cout << "第二本书 ID : " << Book2.book_id <<endl; return 0;}
实例中定义了结构体类型 Books 及其两个变量 Book1 和 Book2。当上面的代码被编译和执行时,它会产生下列结果:
第一本书标题:C++教程
第一本书作者:Runoob
第一本书类目:编程语言
第一本书ID:12345
第一本书标题:CSS教程
第一本书作者:Runoob
第一本书类目:前端技术
第一本书ID:123456
结构作为函数参数
您可以把结构作为函数参数,传参方式与其他类型的变量或指针类似。您可以使用上面实例中的方式来访问结构变量:
#include <iostream>#include <cstring> using namespace std;void printBook( struct Books book ); // 声明一个结构体类型 Books struct Books{ char title[50]; char author[50]; char subject[100]; int book_id;}; int main( ){ Books Book1; // 定义结构体类型 Books 的变量 Book1 Books Book2; // 定义结构体类型 Books 的变量 Book2 // Book1 详述 strcpy( Book1.title, "C++ 教程"); strcpy( Book1.author, "Runoob"); strcpy( Book1.subject, "编程语言"); Book1.book_id = 12345; // Book2 详述 strcpy( Book2.title, "CSS 教程"); strcpy( Book2.author, "Runoob"); strcpy( Book2.subject, "前端技术"); Book2.book_id = 1234556; // 输出 Book1 信息 printBook( Book1 ); // 输出 Book2 信息 printBook( Book2 ); return 0;}void printBook( struct Books book ){ cout << "书标题 : " << book.title <<endl; cout << "书作者 : " << book.author <<endl; cout << "书类目 : " << book.subject <<endl; cout << "书 ID : " << book.book_id <<endl;}
当上面的代码被编译和执行时,它会产生下列结果:
书标题:C++教程
书作者:Runoob
书类目:编程语言
书ID:12345
书标题:CSS教程
书作者:Runoob
书类目:前端技术
书ID:123456
指向结构的指针
您可以定义指向结构的指针,方式与定义指向其他类型变量的指针相似,如下所示:
struct Books *struct_pointer;
现在,您可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,如下所示:
struct_pointer = &Book1;
为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符,如下所示:
struct_pointer->title;
让我们使用结构指针来重写上面的实例,这将有助于您理解结构指针的概念:
#include <iostream>#include <cstring> using namespace std;void printBook( struct Books *book ); struct Books{ char title[50]; char author[50]; char subject[100]; int book_id;}; int main( ){ Books Book1; // 定义结构体类型 Books 的变量 Book1 Books Book2; // 定义结构体类型 Books 的变量 Book2 // Book1 详述 strcpy( Book1.title, "C++ 教程"); strcpy( Book1.author, "Runoob"); strcpy( Book1.subject, "编程语言"); Book1.book_id = 12345; // Book2 详述 strcpy( Book2.title, "CSS 教程"); strcpy( Book2.author, "Runoob"); strcpy( Book2.subject, "前端技术"); Book2.book_id = 1234556; // 通过传 Book1 的地址来输出 Book1 信息 printBook( &Book1 ); // 通过传 Book2 的地址来输出 Book2 信息 printBook( &Book2 ); return 0;}// 该函数以结构指针作为参数void printBook( struct Books *book ){ cout << "书标题 : " << book->title <<endl; cout << "书作者 : " << book->author <<endl; cout << "书类目 : " << book->subject <<endl; cout << "书 ID : " << book->book_id <<endl;}
当上面的代码被编译和执行时,它会产生下列结果:
书标题:C++教程
书作者:Runoob
书类目:编程语言
书ID:12345
书标题:CSS教程
书作者:Runoob
书类目:前端技术
书ID:123456
typedef 关键字
下面是一种更简单的定义结构的方式,您可以为创建的类型取一个"别名"。例如:
typedef struct Books{ char title[50]; char author[50]; char subject[100]; int book_id;}Books;
现在,您可以直接使用 Books 来定义 Books 类型的变量,而不需要使用 struct 关键字。下面是实例:
Books Book1, Book2;
您可以使用 typedef 关键字来定义非结构类型,如下所示:
typedef long int *pint32; pint32 x, y, z;
x, y 和 z 都是指向长整型 long int 的指针。
C++ 数据封装
所有的 C++ 程序都有以下两个基本要素:
-
程序语句(代码):这是程序中执行动作的部分,它们被称为函数。
-
程序数据:数据是程序的信息,会受到程序函数的影响。
封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全。数据封装引申出了另一个重要的 OOP 概念,即数据隐藏。
数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
C++ 通过创建类来支持封装和数据隐藏(public、protected、private)。我们已经知道,类包含私有成员(private)、保护成员(protected)和公有成员(public)成员。默认情况下,在类中定义的所有项目都是私有的。例如:
class Box{ public: double getVolume(void) { return length * breadth * height; } private: double length; // 长度 double breadth; // 宽度 double height; // 高度};
变量 length、breadth 和 height 都是私有的(private)。这意味着它们只能被 Box 类中的其他成员访问,而不能被程序中其他部分访问。这是实现封装的一种方式。
为了使类中的成员变成公有的(即,程序中的其他部分也能访问),必须在这些成员前使用 public 关键字进行声明。所有定义在 public 标识符后边的变量或函数可以被程序中所有其他的函数访问。
把一个类定义为另一个类的友元类,会暴露实现细节,从而降低了封装性。理想的做法是尽可能地对外隐藏每个类的实现细节。
数据封装的实例
C++ 程序中,任何带有公有和私有成员的类都可以作为数据封装和数据抽象的实例。请看下面的实例:
#include <iostream>using namespace std; class Adder{ public: // 构造函数 Adder(int i = 0) { total = i; } // 对外的接口 void addNum(int number) { total += number; } // 对外的接口 int getTotal() { return total; }; private: // 对外隐藏的数据 int total;};int main( ){ Adder a; a.addNum(10); a.addNum(20); a.addNum(30); cout << "Total " << a.getTotal() <<endl; return 0;}
当上面的代码被编译和执行时,它会产生下列结果:
Total 60
上面的类把数字相加,并返回总和。公有成员 addNum 和 getTotal 是对外的接口,用户需要知道它们以便使用类。私有成员 total 是对外隐藏的,用户不需要了解它,但它又是类能正常工作所必需的。
设计策略
通常情况下,我们都会设置类成员状态为私有(private),除非我们真的需要将其暴露,这样才能保证良好的封装性。
这通常应用于数据成员,但它同样适用于所有成员,包括虚函数。
C++ 类 & 对象
C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。
类用于指定对象的形式,是一种用户自定义的数据类型,它是一种封装了数据和函数的组合。类中的数据称为成员变量,函数称为成员函数。类可以被看作是一种模板,可以用来创建具有相同属性和行为的多个对象。
C++ 类定义
定义一个类需要使用关键字 class,然后指定类的名称,并类的主体是包含在一对花括号中,主体包含类的成员变量和成员函数。
定义一个类,本质上是定义一个数据类型的蓝图,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
以下实例我们使用关键字 class 定义 Box 数据类型,包含了三个成员变量 length、breadth 和 height:
class Box{ public: double length; // 盒子的长度 double breadth; // 盒子的宽度 double height; // 盒子的高度};
关键字 public 确定了类成员的访问属性。在类对象作用域内,公共成员在类的外部是可访问的。您也可以指定类的成员为 private 或 protected,这个我们稍后会进行讲解。
定义 C++ 对象
类提供了对象的蓝图,所以基本上,对象是根据类来创建的。声明类的对象,就像声明基本类型的变量一样。下面的语句声明了类 Box 的两个对象:
Box Box1; // 声明 Box1,类型为 Box Box Box2; // 声明 Box2,类型为 Box
对象 Box1 和 Box2 都有它们各自的数据成员。
访问数据成员
类的对象的公共数据成员可以使用直接成员访问运算符 . 来访问。
为了更好地理解这些概念,让我们尝试一下下面的实例:
#include <iostream> using namespace std; class Box{ public: double length; // 长度 double breadth; // 宽度 double height; // 高度 // 成员函数声明 double get(void); void set( double len, double bre, double hei );};// 成员函数定义double Box::get(void){ return length * breadth * height;} void Box::set( double len, double bre, double hei){ length = len; breadth = bre; height = hei;}int main( ){ Box Box1; // 声明 Box1,类型为 Box Box Box2; // 声明 Box2,类型为 Box Box Box3; // 声明 Box3,类型为 Box double volume = 0.0; // 用于存储体积 // box 1 详述 Box1.height = 5.0; Box1.length = 6.0; Box1.breadth = 7.0; // box 2 详述 Box2.height = 10.0; Box2.length = 12.0; Box2.breadth = 13.0; // box 1 的体积 volume = Box1.height * Box1.length * Box1.breadth; cout << "Box1 的体积:" << volume <<endl; // box 2 的体积 volume = Box2.height * Box2.length * Box2.breadth; cout << "Box2 的体积:" << volume <<endl; // box 3 详述 Box3.set(16.0, 8.0, 12.0); volume = Box3.get(); cout << "Box3 的体积:" << volume <<endl; return 0;}
当上面的代码被编译和执行时,它会产生下列结果:
Box1的体积:210
Box2的体积:1560
Box3的体积:1536
需要注意的是,私有的成员和受保护的成员不能使用直接成员访问运算符 (.) 来直接访问。我们将在后续的教程中学习如何访问私有成员和受保护的成员。