【C++】类和对象(上)

简介: 【C++】类和对象(上)

对象的介绍


C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题;

 C++是基于面向对象的,关注的是对象,将一件事拆分成不同的对象,靠对象之间的交互完成,实际上对象这个翻译是不准确的,侯捷在翻译《Effective C++》中就说到,object的真正意义是“物体、物件”而不是“对象、目标”。不过大多数人在学习的时候都被告知了对象的意思是有别于原意,因此程序员对对象这一词的认知应该是要比其他人多一个释义的。

 个人认为对象有点类似于数据库中抽象出的实体,对象就是逻辑上存在这一东西,不是一定要现实中就看得见摸得着,然后它们各自具备能够相互区分的属性。

 举个例子,我要从绵阳到成都。面向过程:买票->进站->候车->检票->乘车->到站->下车->出站;而面向对象则是关注什么与什么交互,我要从绵阳到成都,那对象就是我(或者说人)、车站、车三个对象之间的交互。


类的介绍

  在C语言中,结构体只能用来定义变量。但是C++中的结构体不仅可以定义变量,也能够定义函数。在C++中struct可以被用来实现一个类,但是C++中更常用的还是class。

//这里只是用来说明struct可以实现一个类,之后会用class
typedef int DataType;
struct Stack
{
  void Init(size_t capacity)
  {
    _array = (DataType*)malloc(sizeof(DataType) * capacity);
    if (nullptr == _array)
    {
      perror("malloc申请空间失败");
      exit(-1);
    }
    _capacity = capacity;
    _size = 0;
  }
  void Push(const DataType& data)
  {
    _array[_size] = data;
    ++_size;
  }
  DataType Top()
  {
    return _array[_size - 1];
  }
  void Destroy()
  {
    if (_array)
    {
      free(_array);
      _array = nullptr;
      _capacity = 0;
      _size = 0;
    }
  }
  DataType* _array;
  size_t _capacity;
  size_t _size;
};
int main()
{
  Stack s;
  s.Init(10);
  s.Push(1);
  s.Push(2);
  s.Push(3);
  cout << s.Top() << endl;
  s.Destroy();
  return 0;
}

class是定义的关键字,类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。

类的两种定义方式

  声明和定义全部放在类体中,需要注意的是,如果成员函数在类中定义,编译器可能会将其当成内联函数处理。

class Student
{
public:
  void showInfo()
  {
    cout << _name << "-" << _sex << "-" << _sno << endl;
  }
public:
  char* _name;
  char* _sex;
  int _sno;
};

 类的声明放在.h文件中,成员函数定义放在.cpp文件中。需要注意的是,成员函数名前需要加 类名::

class Teacher
{
public:
  void showInfo();
public:
  char* _name;
  char* _sex;
  int _tno;
};
void Teacher::showInfo()
{
  cout << _name << "-" << _sex << "-" << _tno << endl;
}

0172eb79ea0841d190af71fa3eb58ddd.png

类的访问限定符及封装

访问限定符

C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性将其接口提供给外部的用户使用。

 访问限定符:public(公有)、protected(保护)、private(私有)。

 public修饰的成员在类外可以直接被访问;

 protected和private修饰的成员在类外不能直接被访问;

 访问权限作用域从该访问限定符出现的位置开始到一下个访问限定符出现为止;

 如果后面没有访问限定符,作用域就到类结束为止;

 class的默认权限是private,struct为public(因为要兼容C语言);

 访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别


封装

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

 封装本质上是一种管理,让用户更方便实用类。在C++语言中实现封装,可以通过类将数据以及操作数的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。


类的作用域

  类定义了一个新的作用域,类的所有成员都在作用域中。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。


//这里说明showInfo是属于Teacher这个类域的
void Teacher::showInfo()
{
  cout << _name << "-" << _sex << "-" << _tno << endl;
}

类的实例化

  用类创建对象的过程称为实例化。

  类是对对象的描述,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。只有在实例化之后,才为实例化后的对象开辟了空间。

  一个类可以实例化出多个对象。

class Student
{
public:
  void showInfo()
  {
    cout << _name << "-" << _sex << "-" << _sno << endl;
  }
public:
  char* _name;
  char* _sex;
  int _sno;
};
void test()
{
  Student zs;
  zs._name = (char*)"张三";
  zs._sex = (char*)"男";
  zs._sno = 01;
  zs.showInfo();
}
int main()
{
  test();
  return 0;
}

类的对象模型

类对象在存储时,存储的是成员对象,成员函数并不存放在对象中。每个对象的成员变量是不一样的,但是成员函数是相同的。如果每个对象里面都放一个成员函数,这样并不是一个高效的方法。最好的方法是把成员函数放到一个共享的公共区域里面,然后需要使用时去该区域进行调用。这个区域被叫做代码段。

 所以一个类的大小,实际上就是成员变量的和,因为成员函数被存放在代码段了。类里面的成员变量也需要进行内存对齐,对齐方式与结构体的对齐方式一致。需要注意的是一个空类的大小是一字节,而并非零字节。编译器需要一个标识来识别这个类的对象。


目录
相关文章
|
3天前
|
设计模式 安全 编译器
【C++11】特殊类设计
【C++11】特殊类设计
22 10
|
8天前
|
C++
C++友元函数和友元类的使用
C++中的友元(friend)是一种机制,允许类或函数访问其他类的私有成员,以实现数据共享或特殊功能。友元分为两类:类友元和函数友元。类友元允许一个类访问另一个类的私有数据,而函数友元是非成员函数,可以直接访问类的私有成员。虽然提供了便利,但友元破坏了封装性,应谨慎使用。
39 9
|
4天前
|
存储 编译器 C语言
【C++基础 】类和对象(上)
【C++基础 】类和对象(上)
|
12天前
|
编译器 C++
【C++】string类的使用④(字符串操作String operations )
这篇博客探讨了C++ STL中`std::string`的几个关键操作,如`c_str()`和`data()`,它们分别返回指向字符串的const char*指针,前者保证以&#39;\0&#39;结尾,后者不保证。`get_allocator()`返回内存分配器,通常不直接使用。`copy()`函数用于将字符串部分复制到字符数组,不添加&#39;\0&#39;。`find()`和`rfind()`用于向前和向后搜索子串或字符。`npos`是string类中的一个常量,表示找不到匹配项时的返回值。博客通过实例展示了这些函数的用法。
|
12天前
|
存储 C++
【C++】string类的使用③(非成员函数重载Non-member function overloads)
这篇文章探讨了C++中`std::string`的`replace`和`swap`函数以及非成员函数重载。`replace`提供了多种方式替换字符串中的部分内容,包括使用字符串、子串、字符、字符数组和填充字符。`swap`函数用于交换两个`string`对象的内容,成员函数版本效率更高。非成员函数重载包括`operator+`实现字符串连接,关系运算符(如`==`, `&lt;`等)用于比较字符串,以及`swap`非成员函数。此外,还介绍了`getline`函数,用于按指定分隔符从输入流中读取字符串。文章强调了非成员函数在特定情况下的作用,并给出了多个示例代码。
|
12天前
|
C++
【C++】string类的使用④(常量成员Member constants)
C++ `std::string` 的 `find_first_of`, `find_last_of`, `find_first_not_of`, `find_last_not_of` 函数分别用于从不同方向查找目标字符或子串。它们都返回匹配位置,未找到则返回 `npos`。`substr` 用于提取子字符串,`compare` 则提供更灵活的字符串比较。`npos` 是一个表示最大值的常量,用于标记未找到匹配的情况。示例代码展示了这些函数的实际应用,如替换元音、分割路径、查找非字母字符等。
|
12天前
|
C++
C++】string类的使用③(修改器Modifiers)
这篇博客探讨了C++ STL中`string`类的修改器和非成员函数重载。文章介绍了`operator+=`用于在字符串末尾追加内容,并展示了不同重载形式。`append`函数提供了更多追加选项,包括子串、字符数组、单个字符等。`push_back`和`pop_back`分别用于在末尾添加和移除一个字符。`assign`用于替换字符串内容,而`insert`允许在任意位置插入字符串或字符。最后,`erase`函数用于删除字符串中的部分内容。每个函数都配以代码示例和说明。
|
12天前
|
安全 编译器 C++
【C++】string类的使用②(元素获取Element access)
```markdown 探索C++ `string`方法:`clear()`保持容量不变使字符串变空;`empty()`检查长度是否为0;C++11的`shrink_to_fit()`尝试减少容量。`operator[]`和`at()`安全访问元素,越界时`at()`抛异常。`back()`和`front()`分别访问首尾元素。了解这些,轻松操作字符串!💡 ```
|
12天前
|
存储 编译器 Linux
【C++】string类的使用②(容量接口Capacity )
这篇博客探讨了C++ STL中string的容量接口和元素访问方法。`size()`和`length()`函数等价,返回字符串的长度;`capacity()`提供已分配的字节数,可能大于长度;`max_size()`给出理论最大长度;`reserve()`预分配空间,不改变内容;`resize()`改变字符串长度,可指定填充字符。这些接口用于优化内存管理和适应字符串操作需求。
|
12天前
|
C++ 容器
【C++】string类的使用①(迭代器接口begin,end,rbegin和rend)
迭代器接口是获取容器元素指针的成员函数。`begin()`返回首元素的正向迭代器,`end()`返回末元素之后的位置。`rbegin()`和`rend()`提供反向迭代器,分别指向尾元素和首元素之前。C++11增加了const版本以供只读访问。示例代码展示了如何使用这些迭代器遍历字符串。