C++快速入门1——基础知识

1、this

this是个特殊指针,在class里面指向当前对象,例如。

class Person
{
private:
    char    *name;
public:
    void setName(char *name)
    {
        this->name = name;
    }
};

2、::

  1. 用于指定当前函数属于某个类,例如setAge函数属于Person类的一个方法。
  2. 用于指定调用的函数是来自哪个命名空间,例如调用的是命名空间A里面的PrintVersion函数。
void Person::setAge(int age)
{
    this->age = age;
}

A::PrintVersion();

在这里插入图片描述

3、 using用法:

  1. using A::Person; 声明使用命名空间A里面的Person类,不声明的话在使用类之前要加命名空间。
  2. using A::PrintVersion; 导入命名空间A里面的PrintVersion函数,不声明的话在调用函前面要加命名空间。
  3. 直接using namespace A; 一次性导入命名空间A涉及的类和函数。

4、cout

需要包含头文件iostream:#include ,不需要加.h,引用标准命名空间std。cout使用方法:cout<<"age = “<<age<<”,name = "<<name<<endl;这里的<<是重载了左移运算,达到字符串拼接的效果,enld是回车换行。

cout有时候的输出格式不是我们想要的,如下会输出i = d,需要加强转来解决。

uint8_t i = 100;
cout<<"i = "<<i<<endl;

5、构造函数

  1. 调用无参构造函数的方法:Person person;或者Person person(“zhangsan”,18);而Person person()只是声明一个函数,并不是定义一个类变量。
  2. 构造函数需要public属性。
  3. 指针方式定义类变量:Person *per = new Person;或者Person *per = new Person();这两种方式都是可以的,都会调用无参的构造函数。删除一个类:delete per。
  4. 构造函数传入默认参数,如Person(int age,char *name = “zhangsan”)。
  5. 一旦定义了有参构造函数,则必须定义一个无参构造函数。

6、析构函数

析构函数用户释放一些类里面动态分配的内存,函数定义格式为:类名(),例如Person(),析构函数无参。

7、类的默认函数

  1. 默认构造函数:一个无参的构造函数,函数的内容为空

  2. 默认的析构函数:函数的内容为空

  3. 默认的拷贝函数:是一个特殊的构造函数,其入参是该类的引用。当创建一个类的时候,如果传入的参数是同一个类的引用,那么会拷贝一份,注意传入的参数是类引用,而不是指针。例如:

    Person *per = new Person(25,"Dokin");
    Person *per2 = new Person(*per);
    或
    Person per(25,"Dokin");
    Person per2(per);
    

    类的默认拷贝函数在使用上有风险,因为创建出的类对象,其成员如果是指针类型,会和类引用指向同一空间,在内存分配和释放上就有可能产生被重复释放的问题,这种情况下需要重写拷贝函数。

8、构造函数调用顺序

  1. 按运行中定义对象的顺序调用构造函数,静态对象只调用一次构造函数,全局对象在main函数执行前被构造。

  2. 类定义中如果使用了别的类,那么会先按编码顺序依次调用别的类的构造函数,然后再调用本类的构造函数。

    扫描二维码关注公众号,回复: 12978590 查看本文章
  3. 类的构造函数需要构造别的类时,在构造函数后面加:号,多个类用,隔开。如下面例子所示。注意,构造顺序和:后面的顺序无关,只和定义类成员的顺序有关,即下面的例子依然是father先被构造。析构的顺序则和构造的顺序刚好相反。

    class Student
    {
    private:
        Person father;
        Person mother;
        int age;
    public:
        Student(){}
        Student(int age,char *father,int father_age,char *mother,int mother_age)\
            :mother(mother,mother_age),father(father,father_age)
        {
            this->age = age;
        }
    };
    
    int main(int argc,char **argv)
    {
        Student Dokin(15,"bill",40,"lily",39);
        return 0;
    }
    

9、类的静态成员和方法

类里面可以使用static对成员和方法进行修饰,表明该成员或方法属于类,而不是属于类的实例对象。

类的静态成员即使是private权限,也可以通过类名来直接访问。

静态方法只能访问静态变量,不能访问非静态变量,因为静态变量属于类,而非静态变量属于类的实例对象。

类的实例对象也可以访问类的静态方法。

类的静态方法可以在类里面声明然后类的外面定义,例如:

class Person
{
private:
    static int cnt;
public:
    static int getCnt();
    /* ... */
}

int Person::getCnt()
{
    return Person::cnt;
}

类定义时并没有分配内存空间,因此需要在外部进行定义和初始化,下面是一个例子。

class Person
{
private:
    char    *name;
    int     age;
    static int cnt;

public:
    Person()
    {
        cnt ++;
        this->name = NULL;
    }
    ~Person()
    {
        cnt --;
    }
    static int getCnt()
    {
        return cnt;
    }
}

int Person::cnt = 0;

int main(int argc,char **argv)
{
    Person per1;
    Person per2;
   	
    cout<<"cnt = "<<Person::getCnt()<<endl;
}

10、友元函数

在类的定义中,可以用friend关键字来声明一个友元函数,友元函数可以直接访问所在类的私有成员,从而提高效率。下面是一个例子。

#include <iostream>
using namespace std;

class Point
{
private:
    int x;
    int y;

public:
    Point(){}
    Point(int x,int y):x(x),y(y){}
    void print()
    {
        cout<<"x = "<<x<<",y = "<<y<<endl;
    }
    friend Point addPoint(Point &p1,Point &p2);
};

Point addPoint(Point &p1,Point &p2)
{
    Point point;

    point.x = p1.x + p2.x;
    point.y = p1.y + p2.y;

    return point;
}

int main(int argc,char **argv)
{
    Point p1(1,2);
    Point p2(3,4);
    Point p3 = addPoint(p1,p2);

    p3.print();
}

11、const成员函数

在成员函数后面加上const表示此函数没有修改操作,如void printInfo(void)const。

12、运算符重载

例如重载++号运算,那么函数名为Point operator++(Point p),通过入参的不同可以实现运算符的不同功能,例如以下++的实现。

/* 实现++p */
Point operator++(Point &p)
{
    p.x += 1;
    p.y += 1;
    return p;
}

/* 实现p++ */
Point operator++(Point &p, int a)
{
    Point temp;
    
    temp = p;
    p.x += 1;
    p.y += 1;
    return temp;
}

上述函数通过函数入参的不同实现了函数重载,实现了前++和后++。

注意Point operator++(Point &p)函数中定义了返回了一个临时变量p,这会造成临时变量p的构造函数和析构函数被调用,从而影响函数执行效率,最佳的实现方式如下,返回一个引用,这样就不会有临时变量,也就不会调用构造函数和析构函数了。

/* 实现++p */
Point& operator++(Point &p)
{
    p.x += 1;
    p.y += 1;
    return p;
}

重载=号运算符可以解决值拷贝造成的问题:拷贝类的指针成员,导致两个类的成员指向同一块地址。重载=号可以在重载函数里对指针成员进行内存申请和销毁,避免指向同一地址。

以下操作的结果是不同的:p2 = p1会调用默认的拷贝函数,而不是调用operator=重载函数。先定义p3,然后p3=p1这样才会调用operator=重载函数。

Person p1;
Person p2 = p1;

Person p3;
p3 = p1;

猜你喜欢

转载自blog.csdn.net/qq_27575841/article/details/112974599