首页 > 编程语言 >突击-C++

突击-C++

时间:2023-06-25 23:55:23浏览次数:32  
标签:友元 函数 area 成员 C++ 线程 基类 突击

C++完全支持面向对象的程序设计,包括面向对象开发的四大特性:

  • 封装: 是将数据和方法组合在一起,对外部隐藏实现细节,只公开对外提供的接口。这样可以提高安全性、可靠性和灵活性。
  • 继承: 是从已有类中派生出新类,新类具有已有类的属性和方法,并且可以扩展或修改这些属性和方法。这样可以提高代码的复用性和可扩展性。
  • 多态: 是指同一种操作作用于不同的对象,可以有不同的解释和实现。它可以通过接口或继承实现,可以提高代码的灵活性和可读性。
  • 抽象: 是从具体的实例中提取共同的特征,形成抽象类或接口,以便于代码的复用和扩展。抽象类和接口可以让程序员专注于高层次的设计和业务逻辑,而不必关注底层的实现细节。

 

标准的C++由三个重要部分组成:

  • 核心语言,提供了所有构件块,包括变量、数据类型和常量,等等。
  • C++标准库,提供了大量的函数,用于操作文件、字符串等。
  • 标准模板库(STL),提供了大量的方法,用于操作数据结构等。

 

引用很容易与指针混淆,它们之间有三个主要的不同:

  • 不存在空引用。引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
  • 引用必须在创建时被初始化。指针可以在任何时间被初始化。

 

I/O 库头文件

<iostream>

该文件定义了和对象,分别对应于标准输入流、标准输出流、非缓冲标准错误流和缓冲标准错误流。

标准输出流(cout)

 cout是与流插入运算符 << 结合使用的

标准输入流(cin)

cin 是与流提取运算符 >> 结合使用的

C++ 编译器根据要输入值的数据类型,选择合适的流提取运算符来提取值,并把它存储在给定的变量中。

 

命名空间可作为附加信息来区分不同库中相同名称的函数、类、变量等。

一个文件夹(目录)中可以包含多个文件夹,每个文件夹中不能有相同的文件名,但不同文件夹中的文件可以重名

定义命名空间:

namespace namespace_name {

    //代码声明

}

调用带有命名空间的函数或变量:

name::code;  // code 可以是变量或函数

例子:

#include <iostream>
using namespace std;
 
// 第一个命名空间
namespace first_space{
   void func(){
      cout << "Inside first_space" << endl;
   }
}
// 第二个命名空间
namespace second_space{
   void func(){
      cout << "Inside second_space" << endl;
   }
}
int main ()
{
 
   // 调用第一个命名空间中的函数
   first_space::func();
   
   // 调用第二个命名空间中的函数
   second_space::func(); 
 
   return 0;
}

相同的函数命名为func()。

 

using指令

可以使用 using namespace 指令,这样在使用命名空间时就可以不用在前面加上命名空间的名称。

例如:

#include <iostream>
using namespace std;
 
// 第一个命名空间
namespace first_space{
   void func(){
      cout << "Inside first_space" << endl;
   }
}
// 第二个命名空间
namespace second_space{
   void func(){
      cout << "Inside second_space" << endl;
   }
}
using namespace first_space;
int main ()
{
 
   // 调用第一个命名空间中的函数
   func();
   
   return 0;
}

 

 

动态内存

栈:在函数内部声明的所有变量都将占用栈内存。

堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存。

在 C++ 中,你可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址。这种运算符即 new 运算符。

如果你不再需要动态分配的内存空间,可以使用 delete 运算符,删除之前由 new 运算符分配的内存。

 

类和对象

类是 C++ 的核心特性,通常被称为用户定义的类型。类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。

 

类成员函数

成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义。调用成员函数是在对象上使用点运算符“.”

 

类访问修饰符

关键字 public、private、protected 称为访问修饰符。

一个类可以有多个 public、protected 或 private 标记区域。成员和类的默认访问修饰符是 private。

 

公有(public)成员

公有成员在程序中类的外部是可访问的。您可以不使用任何成员函数来设置和获取公有变量的值

私有(private)成员

私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。

受保护(protected)成员

与私有成员十分相似,但protected(受保护)成员在派生类(即子类)中是可访问的。

 

友元函数

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend。

 

this指针

每一个对象都能通过 this指针来访问自己的地址。this指针是所有成员函数的隐含参数。友元函数没有 this 指针,因为友元不是类的成员。

 

继承允许我们依据另一个类来定义一个类。

当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。

 

重载

重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。

 

多态

多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

例子:

#include <iostream> 
using namespace std;
 
class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
class Rectangle: public Shape{
   public:
      Rectangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};
class Triangle: public Shape{
   public:
      Triangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};
// 程序的主函数
int main( )
{
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);
 
   // 存储矩形的地址
   shape = &rec;
   // 调用矩形的求面积函数 area
   shape->area();
 
   // 存储三角形的地址
   shape = &tri;
   // 调用三角形的求面积函数 area
   shape->area();
   
   return 0;
}

输出结果:

Parent class area :

Parent class area :

调用函数 area() 被编译器设置为基类中的版本,这就是所谓的静态多态,或静态链接 - 函数调用在程序执行前就准备好了。

在 Shape 类中,area() 的声明前放置关键字 virtual,例如:

class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      virtual int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};

输出结果:

Rectangle class area :

Triangle class area :

由于 tri 和 rec 类的对象的地址存储在 *shape 中,所以会调用各自的 area() 函数。这就是多态的一般使用方式。有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。

 

 

虚函数

在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。

  1. 虚函数的定义:在基类中使用 virtual 关键字声明的成员函数称为虚函数。派生类可以重写(覆盖)基类的虚函数,以实现多态性。

  2. 多态性(Polymorphism):虚函数是实现多态性的关键机制。通过将基类指针或引用指向派生类对象,并调用虚函数,可以根据实际对象的类型来确定调用的函数版本。

  3. 动态绑定(Dynamic Binding):虚函数在运行时进行动态绑定,而不是在编译时进行静态绑定。这意味着程序在运行时能够确定要调用的函数版本,而不是根据变量的声明类型。

  4. 虚函数表(Virtual Function Table):编译器为包含虚函数的类创建虚函数表,也称为 vtable。虚函数表是一个指针数组,其中存储了每个虚函数的地址。每个对象都有一个指向虚函数表的指针,用于在运行时查找正确的虚函数。

  5. 纯虚函数(Pure Virtual Function):通过在基类中将函数声明为纯虚函数(使用 virtual 关键字,并将函数定义设置为0),可以创建抽象基类。抽象基类无法实例化,而只能被继承并在派生类中实现纯虚函数。

  6. 虚析构函数(Virtual Destructor):在基类中使用虚析构函数可以确保在删除指向派生类对象的基类指针时正确地调用派生类的析构函数,以避免内存泄漏。

  7. 虚函数的性能开销:使用虚函数会引入额外的性能开销,因为它涉及虚函数表的查找和函数调用的间接性。但在大多数情况下,这种开销是可以接受的,特别是在需要实现多态性的情况下。

 

多线程

创建线程

CreateThread 用于创建一个线程,其函数原型如下:

HANDLE WINAPI CreateThread(
    LPSECURITY_ATTRIBUTES   lpThreadAttributes, //线程安全相关的属性,常置为NULL
    SIZE_T                  dwStackSize,        //新线程的初始化栈在大小,可设置为0
    LPTHREAD_START_ROUTINE  lpStartAddress,     //被线程执行的回调函数,也称为线程函数
    LPVOID                  lpParameter,        //传入线程函数的参数,不需传递参数时为NULL
    DWORD                   dwCreationFlags,    //控制线程创建的标志
    LPDWORD                 lpThreadId          //传出参数,用于获得线程ID,如果为NULL则不返回线程ID
);

线程函数的原型如下:

DWORD WINAPI ThreadProc(LPVOID lpParameter);    //lpParameter是传入的参数,是一个空指针

终止线程

CloseHandle()用于终止线程

 

标签:友元,函数,area,成员,C++,线程,基类,突击
From: https://www.cnblogs.com/wxk1213/p/17504293.html

相关文章

  • C++面试八股文:std::array如何实现编译器排序?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第25面:面试官:array熟悉吗?二师兄:你说的是原生数组还是std::array?面试官:你觉得两者有什么区别?二师兄:区别不是很大,原生数组(非动态数组)和std::array都在栈上开辟空间,初始化的时候需要提供数组长度,且长度不可改变。有一点区别的是,st......
  • C++面试八股文:std::array如何实现编译器排序?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第25面:面试官:array熟悉吗?二师兄:你说的是原生数组还是std::array?面试官:你觉得两者有什么区别?二师兄:区别不是很大,原生数组(非动态数组)和std::array都在栈上开辟空间,初始化的时候需要提供数组长度,且长度不可改变。有一点区别的是,std......
  • C++ 核心指南之资源管理(中)
    C++核心指南之资源管理(中)R.alloc:分配和释放R.10:避免使用malloc()/free()R.11:避免显式调用new/deleteR.12:显式资源分配的结果应立即给到资源管理对象R.13:在一条语句中,最多只能有一个显式资源分配R.14:避免使用[]参数,用span替代R.15:分配/释放操作要......
  • C++ 数据抽象
     数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节。数据抽象是一种依赖于接口和实现分离的编程(设计)技术。让我们举一个现实生活中的真实例子,比如一台电视机,您可以打开和关闭、切换频道、调整音量、添加外部组件(如喇叭、录像机、DVD播......
  • C/C++C/C++语言课程设计参考题目[2023-06-25]
    C/C++C/C++语言课程设计参考题目[2023-06-25]《高级程序设计技术综合课程设计》C/C++语言课程设计参考题目目录信息管理类 1工资管理系统 1职工工资信息管理系统 2职工工资管理系统 2院职工工资管理系统 3公司职工工资管理系统 3工资纳税计算系统 3校际运动会管理系统......
  • C++面试八股文:std::string是如何实现的?
    C++面试八股文:std::string是如何实现的?某日二师兄参加XXX科技公司的C++工程师开发岗位第18面:面试官:std::string用过吧?二师兄:当然用过(废话,C++程序员就没有没用过std::string的)。面试官:std::string("hello")+"world"、"hello"+std::string("world")和std::string("hello")......
  • Qt/c++类型转换总结
    1、static_cast、dynamic_cast、强制转换(reinterpret_cast和const_cast)、qobject_cast、qstatic_cast以及qdynamic_cast的区别:static_cast:用于执行静态类型转换,可以进行常见的类型转换,例如基本类型之间的转换、向上转型、向下转型(但没有运行时类型检查)等。在C++中......
  • C/C++ 类型显式转换
    上一章,我提到了下面的代码#include<stdio.h>inta=(long)4;externchark=(int)'m';voidmain(void){printf("%s",a);printf("%f",k);}这里我需要纠正上一篇文章的错误,C语言不存在bool类型只要数字是大于0,那么相当于true否则就是false 其中,inta表示......
  • C++面试八股文:std::vector和std::list,如何选择?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第24面:面试官:list用过吗?二师兄:嗯,用过。面试官:请讲一下list的实现原理。二师兄:std::list被称为双向链表,和C中手写双向链表本质上没有大的区别。list对象中有两个指针,一个指向上一个节点(node),一个指向下一个节点(node)。二师兄:与手写......
  • C++面试八股文:std::vector和std::list,如何选择?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第24面:面试官:list用过吗?二师兄:嗯,用过。面试官:请讲一下list的实现原理。二师兄:std::list被称为双向链表,和C中手写双向链表本质上没有大的区别。list对象中有两个指针,一个指向上一个节点(node),一个指向下一个节点(node)。二师兄:与手......