C++基础知识

1、基本概念

1.1 引用类型(reference)

         对一个数据可以使用" 引用 " reference )类型,这是 C++ C 的一个重要扩充,引用是一种新的变量类型,它的作用是为一个变量起一个别名
int a; int &b = a;
        在声明变量 b 时变量 a 的引用后,在它们所在函数执行期间,该引用类型变量 b 始终与其代表的变量 a 相联系,不能再作为其他变量的引用( 别用 ) ,意思是 " 企图使 b 又变成其他变量的引用是不行的 "
        C++之所以增加引用类型,主要是把它作为函数参数,以扩充函数传递数据的功能。指针变量要另外开辟内存单元,其内容是地址,而引用变量不是一个独立的变量,不单独占内存单元。这种传递方式比使用指针比变量简单、直观、方便。使用变量的引用,可以代替部分指针的操作。引用不仅可以用于变量,也可以用于对象。
示例代码:
#include <iostream>
using namespace std;

//typedef //类型重定义
/*
    C语言使用指针存储变量的地址 可以由指针对变量操作

    C++语言弱化指针的概念,引入了 引用 的概念
    格式:类型 &引用变量名 = 需要引用的变量
    [C语言中的空指针NULL C++中空指针nullptr]

*/
void exchange(int &x, int &y);
int main()
{
    /*
        int a = 10;
        int *p = &a;        //int*类型的指针p指向int类型变量
        *p = 50;            //将a改为50

        int &b = a;
        cout << b << endl;  //引用就是给变量起别名,引用必须和要引用的变量是同类型

        char m = 'A';
        char &n = m;
        cout << n << endl;  //通过引用也可以修改原有变量的内容
        n = 'a';
        cout << n << endl;
    */

    int a = 10;
    int b = 40;
    int &c = a;

    //c = b;          //引用无法修改指向
    exchange(a, b);
    cout << a << "  " <<b << endl;
    return 0;
}

/* 引用的产生主要是为了函数传参(传参类的对象) */
void exchange(int &x, int &y){
    int temp = 0;
    temp = x;
    x = y;
    y = temp;
}
/*
    引用 和 指针的区别
    1. 指针是一个变量,占8字节(64系统),系统会为其分配至地址
        引用不是变量,不占空间,只是原本变量的别名
    2. 指针可以修改指向,但是引用一旦定义就无法修改指向,因为依赖于变量存在
    3. 指针定义的时候可以不初始化,但是引用定义的同时必须初始化
*/

 2.2 内置函数(inline-function

        C++提供一种提高效率的方法,即在编译时将所调用函数的代码直接嵌入到主调函数中,而不是将流程转出去。这种嵌入到主调函数中的函数称为内置函数(inline function ),又称内嵌函数。指定内置函数的方法很简单,只需在函数首行的左端加一个关键字 inline 即可。
        内置函数中不能包括复杂的控制语句,如循环语句和 switch 语句。
        应当说明:对函数作 inline 声明,只是程序设计者对编译系统提出的一个建议,也就是说它是建议性的,而不是指令性的。并非一经指定为 inline ,编译系统就必须这样做。编译系统会根据具体情况决定是否这样做,例如对前面提到的包含循环语句和 switch 语句的函数或一个递归函数是无法进行代码置换的,又如一个 1000 行的函数,也不大可能在调用点展开。此时编译系统就会忽略 inline 声明,而按普通函数处理。
        总结,只有那些规模较小而又被频繁调用的简单函数,才适合于声明为内置函数。
示例代码:
#include <iostream>
using namespace std;

/*
	内置函数 / 内联函数 / 内嵌函数
	
	称以下体积较小并且逻辑简单,调用次数较多的函数为内置函数
	如果函数体内部逻辑复杂,while,for,if等判断循环分支语句都不建议设置为内置函数

	格式:在函数名称前加上关键字inline
		[加上关键字知识给编译器提建议,具体是否将函数设置为内置函数还是要看编译器的判断结果]
		[如果函数过于复杂,编译器将函数看作普通函数对待]
*/

/*

如果在程序中要重复多次的执行简单动作,例如函数
跳转时间 1ms
函数执行时间 0.5ms
函数如果在程序中调用100次 跳转时间一共就100ms
如果函数体转换时间花费较多可以将函数设置为内联函数
 实现过程:

	将实参传给形参,将形参拷贝到函数体内部
	再将函数体内部执行程序替换到主程序中调用该函数的位置

*/
inline void printInfo(string name, int id){
	cout << name << "  " << id << endl; 
}

int main(){
	printInfo("A", 1000);
	printInfo("B", 1001);
	printInfo("C", 1002);

	
	cout << "D" << "  " << 1003 << endl; 
	//....

	return 0;

2.3函数重载(function-overloading

        C++允许用同一个函数名定义多个函数,这些函数的参数个数和参数类型不同,这就是函数的重载。即对一个函数名重新赋予它新的含义,使一个函数名可以多用。
        重载函数除了允许参数类型不同以外,还允许参数的个数不同。

2.4函数模板(function-template)

        C++提供了函数模板。所谓的函数模板,实际上是建立一个通用函数,其函数类型和参数类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板,凡是函数体相同的函数都可以用这个模板来代替,不必定 义多个函数,只需再模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。
通用类型定义 
template <typename XXX> 
template 的含义是"模板",
<>中先写关键字 typename 或 class ,后边跟一个类型参数 
XXX,类似标识符, 是一个虚拟的类型名

2.5 动态内存分配

        在软件开发的过程中,常常需要动态地分配和撤销内存空间、例如对动态链表中节点的插入和删除。C 语言中 是利用库函数 malloc free 来分配和撤销内存空间的,而 C++ 则提供了较为简便且功能较强的运算符 new 和 delete 来取代 malloc free 函数。
         需要注意的是,new 和 delete 是运算符,不是函数,因此执行效率更高。为了与 C 语言兼容,C++仍保留了malloc 和 free 函数,但不建议使用,更推荐使用 new 和 delete
/* 开辟一个存放整型的存储空间,返回一个指向该存储空间的地址(指针) */ 
int *p = new int; 
/* 开辟一个存放整型的存储空间,并指定该整数的初值为 100 */ 
int *p = new int(100); 
/* 开辟一个存放二维整型数组的空间,返回首元素的地址 */ 
int (*p)[4] = new int[5][4]; 
new 运算符使用的一般格式为:new 类型(初值) 用 new 分配数组空间时不能指定初值。 
如果由于内存不足等原因而无法正常分配空间,则 new 会返回一个空指针 NULL,用户可以根据该指针的值判 断分配空间是否成功。 delete 运算符使用的一般格式为:delete []指针变量 对基本数据类型的申请可以直接释放。 
如果是类似"char *pt = new char[10]"申请的字符数组空间(构造数据类型空间),释放时应在指针变量前 加一对方括号,表示是对数组空间的操作:delete []pt;
#include <iostream>
using namespace std;

/*
    C语言中使用malloc free进行堆区空间的申请和释放
        void * malloc()

    C++ 使用new delete
*/

typedef struct Person{
    string name;
    int age;
}P_t;
int main(){
    int *p = new int;	//申请4字节空间
    int *q = new int(50);	//申请4字节空空间的同时初始化
    *p = 100;
    cout << *p << endl;		//100
    cout << *q << endl;		//50

    int *t = new int[10];	//申请10个连续的4字节空间
    for(int i=0; i<10;i++){	//循环初始化
        *(t+i) = i;
    }
    for(int i=0; i<10;i++){
        cout << *(t+i) << endl;
    }

    int *T = new int[5]{8,5,2,3,0};	//申请同时初始化
    for(int i=0; i<5;i++){
        cout << *(T+i) << endl;
    }

    struct Person *L = new P_t{("Zhang"), 90};

    delete p;
    delete q;
    delete []t;           //动态申请的连续空间在释放时要加上[]
    delete []T;
    delete L;

    return 0;
}

2、概念升级

2.1 类的定义和使用

        定义类需要使用关键字 class ,然后指定类的名称。类的主体是包含在一对花括号中,其中包含成员变量和成员函数。定义一个类,本质上是定义一个数据类型的蓝图,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
class 类名 
{访问修饰符: // 
属性 type name; // 
方法 type method(); };
// 和结构体类型定义相同 类的定义需要以分号结尾
        类用来创建对象,对象中的数据成员可以使用运算符"." 进行访问,类不仅可以创建对象变量,也可以创建对象指针,对象指针访问数据成员则使用运算符" -> " ,这一点和结构体类似。
示例代码:
#include <iostream>
using namespace std;
/*
 * 在C语言结构体中不能定义或者实现函数,在c++中结构体可以
 * 在类中也可以直接定义以及实现函数
 *  类  class
 *  类中的内容:分为两种变量(属性)和函数(方法)
 *  定义类的格式:
 *      class 类名{
 *          //类中的成员函数以及成员变量
 *      }
 *
 *  类中成员有三种访问修饰符 public protected private
 *  public:公开成员,类内类外都可以访问
 *  protected: 保护成员,类内可以访问,类外不能访问,但是继承类可以访问
 *  private:私有成员,类外不可访问,继承类也不能,友元类和友元函数可以访问
 *
 *  类中如果没有任何访问修饰符,那么全部成员是私有的
 */
class myclass{
public:
    string name;
    int age;
    friend void friendFunc();           //声明友元函数,此类中的私有成员在友元函数种可以访问问
    friend class fclass;
    void inputInfo(string t_name, int t_age){
        name = t_name;
        age = t_age;
    }
    void ouptInfo(){
        cout << "name=" + name << "  " << "age=" << age <<endl;
    }
private:
    int private_num;
};

void friendFunc(){
    myclass user2;
    user2.private_num = 100;   //在友元函数种访问私有成员
}

int main()
{
    //使用自定义的类定义对象 -- 实例化类
    myclass user;

    //调用成员函数对成员变量赋值
    user.inputInfo("Zhang", 20);
    user.ouptInfo();

    return 0;
}

2.2构造函数/析构函数

myclass.h:

#ifndef MYCLASS_H
#define MYCLASS_H
#include <iostream>
using namespace std;
/*
 * 构造函数和析构函数由系统生成并调用,不由用户调用
 *  构造函数在对象生命周期开始的时候被调用
 *  析构函数在生命周期结束时候被调用

*/

class myclass{
public:
    //无参构造函数-默认
    myclass();             //构造函数函数名和类名相同,没有返回值,可以传参数,可以被重载
    ~myclass();            //构造函数函数名是类名加上~,没有返回值,不可以传参数,不可以被重载
                           //如果在类内显式声明构造函数就要实现

    myclass(string name, int age);              //构造函数重载
    myclass(string name, int age, char sex);    //构造函数重载
    myclass(const myclass &obj);                //拷贝构造函数-将另外一个对象的全部内容拷贝给当前的对象
                                                //编译器也会自动生成拷贝构造函数可以直接使用
    void outputInfo(){              //该函数为公开函数,可以在类外访问该函数,间接访问或者修改私有成员
        cout << name << endl;
        cout << age << endl;
        cout << sex <<endl;
        //this->name; //在普通成员函数内可以使用this
    }
    static int num;     //静态成员变量

    static void static_func(){
        //cout << this << endl;     //静态成员函数中不能使用this
        cout << "staic func " << endl;
    }

protected:
private:		//私有成员 类外无法访问 [友元函数可以]
    string name = "Zhang";
    int age;
    char sex;
};


#endif // MYCLASS_H

myclass.cpp:

#include "myclass.h"

myclass::myclass(){
  cout << "无参构造函数:" << name <<"生命周期开始" <<  endl;
}

myclass::~myclass(){
  cout << "析构函数:" << name <<"生命周期结束" <<  endl;
}

//构造函数重载
myclass::myclass(string name, int age){
    this->name = name;              //在函数体内部初始化成员变量
    this->age = age;
    cout << "有参构造函数:" << name <<"生命周期开始" <<  endl;
}
//this指针:只能在类内的成员函数中使用,指向调用成员函数的对象,是一个无类型的指针(静态成员函数中不能用this指针)


//构造函数重载--形参初始化列表  -> 要初始化的成员名称(形参) 以逗号分隔开
myclass::myclass(string name, int age, char t_sex) : name(name), age(age), sex(t_sex){
    cout << "有参构造函数:" << name <<"生命周期开始" <<  endl;
}

//拷贝构造函数 自定义并实现
myclass::myclass(const myclass &obj){
    name = obj.name;
    age = obj.age;
    sex = obj.sex;
}

main.cpp:

#include "myclass.h"

//在c++源文件种,可以定义结构体在结构体定义并实现函数
//结构体种的函数默认的访问修饰符public
//也可以使用其他两个修饰符

//结构体类型    变量
//类 (数据类型) 对象(变量)

int myclass::num = 80;			//静态成员函数必须在类外部定义一次

int main()
{
/*
    myclass u1;             //对象的生命周期开始
    myclass u2("Wang", 50); //有参构造函数--重载
    u2.outputInfo();

    myclass u3("Liu", 10, 'm');  //有参构造函数--重载
    u3.outputInfo();

    myclass u4(u3);         //拷贝 构造函数
    u4.outputInfo();
*/
    myclass user;
    myclass::static_func();         //静态成员变量以及静态成员函数访问方式
                                    //1. 使用类定义对象,通过对象进行访问
                                    //2. 直接使用类加上访问限定符访问静态成员(变量/函数)
    cout << myclass::num++ << endl; //80
    cout << myclass::num++ << endl; //81
    cout << myclass::num << endl;   //82

    return 0;
}

2.3继承/抽象类/虚函数/多态

#include <iostream>
using namespace std;

/* 基类 父类 */
class Parent{
public:                 //类内外
    string name;

    Parent(){
        cout << "父类的无参构造函数" << endl;
    }
    Parent(int num){
        this->private_num = num;
        cout << "父类的构造函数重载" << endl;
    }

    void outputInfo(){
        cout << name << endl;
        cout << age << endl;
    }

    virtual void buy(){
        cout << "父类 全价" << endl;
    }

protected:          //只能在类内访问和派生类中访问
    int age;

private:            //只能在类内访问 和 友元函数内
    int private_num;
};


/* 派生类 子类 */
//格式 class 类名 : 继承方式 父类名称{}
class Child : public Parent{
    //默认存在基类中公开的成员
    //可以再定义一些派生类的成员
public:
    Child(){
        cout << "子类的无参构造函数" << endl;
    }
    virtual void buy(){         //覆盖  override重写
        cout << "子类 半价" << endl;
    }
};

class abclass{
public:
     virtual void abfunc() = 0;            //纯虚函数  含有纯虚函数的类叫做抽象类-无法实例化的类
};

//如果继承自抽象类的派生类不重写基类中的纯虚函数,那么派生类也是抽象类,无法实例化
class son_abclass: public abclass{          //抽象类的派生类
public:
    virtual void abfunc() override{
        cout << "这是派生类的重写" << endl;
    }
};

void func(Parent &p){
    p.buy();
}

//多态:不同对象调用同一接口时有不同的动作
int main()
{
    //使用派生类定义对象  可以直接访问基类中的公开成员
    //Child child1;
/*
    Parent p1;      //基类对象
    Child c1;       //派生类对象

    Parent *P;
    P = &p1;
    P->buy();		//如果基类和派生类没有加上virtual,那么此处和79行P->buy()都会调用基类中的buy函数

    P = &c1;
    P->buy();		//如果在基类以及子类中的成员函数都没有使用virtual进行修饰==没有满足多态
    				//那么调用函数时会根据指针的类型调用,也就是说基类的指针指向子类成员(此时指针类型为基类)
    				//也会调用基类中的成员函数而不是派生类的成员函数
*/

/*
    Parent p1;      //基类对象
    Child c1;       //派生类对象

    func(p1);
    func(c1);

*/

    return 0;
}

(仅供参考学习)

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值