C++进阶知识点(2)内联函数 函数指针 类的构造函数

1.为函数的参数赋予默认值,如果给函数的某个参数设置了默认值,那么参数列表中该参数后面的所有参数都必须有默认值,调用函数的时候如果希望参数使用自己的默认值,只要不传入那个参数就可以了;

void test5(int a,int b = 5,int c = 10,int d =15){
    cout<<a+b+c+d<<endl;
}
int main(int argc,char *argv[]){
    test5(5);
    test5(5,100);
}
 
2.内联函数,在函数的返回类型前面加上inline就可以将这个函数声明为内联函数,声明为内联函数的函数在被调用的时候,相当于将内联函数出的代码代入调用处直接执行。
这样就可以减少部分函数调用产生的开销。但是只适用于那些调用比较频繁,并且函数中代码逻辑较简单的函数。
inline int getBiggerNum(int a,int b){
  return a>b?a:b;

 

3.assert预处理宏的使用,头文件#include <cassert>

使用方法assert(表达式),如果表达式为真则什么也不做,如果表达式为假则输出信息并立即终止程序

int main(int argc,char *argv[]){
    assert(argc>2);
    cout<<"程序执行完毕!"<<endl;
}
 
4.通过预处理变量是否定义来确定代码是否执行:
#ifdef TEST//如果定义了TEST预处理变量则执行下面的代码
    cout<<__func__<<endl;//打印当前函数的名称
    cout<<__FILE__<<endl;//打印当前的文件名
    cout<<__LINE__<<endl;//打印当前的行号
    cout<<__TIME__<<endl;//打印当前的时间
    cout<<__DATE__<<endl;//打印当前的日期
    #endif
这里定义TEST预处理变量的方式,可以在代码前面加上#define TEST。也可以在编译的时候通过命令选项定义TEST预处理变量如:g++ test.cpp -D TEST -o test
 
5.指向函数的指针。
我们可以定义一个指向函数的指针:
函数本身:
int add(int x,int y){
  return x+y;
}
定义一个上面那个函数类型的指针:
int (*funPtr)(int x,int y);//定义一个指向返回值为int,参数为两个int的函数的指针funPtr
funPtr = add;//给函数指针funPtr赋值让其指向上面声明的add函数
funPtr(5,6);//使用这个指向函数的指针调用函数
 
6.将函数指针作为函数的参数传入。
函数的参数也可以是函数的指针,将这个函数指针传入到函数内部后,函数的内部可以通过这个函数指针调用指向的函数。
int add(int x,int y){
    return x+y;
}
int test6(int z,int (*fun)(int x,int y)){//这个函数的第二个参数是一个函数的指针
    return fun(5,6) +z;//调用传入的函数
}
int main(int argc,char *argv[]){
    int rel = test6(7,add);
    cout<<rel<<endl;
}
 
7.将函数指针作为函数的返回值使用
int add(int x,int y){
    return x+y;
}
using FunType = int (*) (int,int);//由于函数指针类型比较长这里使用类型别名的方式为函数指针类型声明一个别名
FunType test7(){
    return add;
}
int main(int argc,char *argv[]){
    int rel = test7()(5,6);//调用test7函数返回一个函数指针,再通过这个函数指针调用指向的函数得到返回结果
    cout<<rel<<endl;
}
 
8.定义类的函数的时候,声明必须在类的内部,定义可以在类的内部也可以在类的外部。定义在类内部的成员函数是隐式的内联函数。
成员函数定义在类内部:
struct Person
{
    string Name="maycpou";
    string getName(){
        return this->Name;
    }
};
int main(int argc,char *argv[]){
    Person per;
    cout<<per.getName()<<endl;
}
成员函数定义在类外部:
struct Person
{
    string Name="maycpou";
    string getName();  
};
string Person::getName(){
    return this->Name;
}
int main(int argc,char *argv[]){
    Person per;
    cout<<per.getName()<<endl;
}
 
9.在定义一个类的时候如果我们没有显示的声明构造函数,编译器会默认给该类加上一个参数为空的构造函数。如果我们显示的声明了构造函数,那么编译器就不会自动帮我们加上那个默认参数为空的构造函数了。
构造函数可以出现在类的内部也可以是在类的外部。
构造函数定义在类的外部:
struct Person
{
    Person(string name);
    string Name="maycpou";
    string getName();  
};
string Person::getName(){
    return this->Name;
}
Person::Person(string name){
    this->Name = name;
}
int main(int argc,char *argv[]){
    Person per("tttttt");
    cout<<per.getName()<<endl;
}
C++11中还新增使用=dafault的方式来添加默认的构造函数,用法见博文C++11新特性
 
10.在我们定义一个类的时候,编译器会替我们生成这个类生成执行赋值,拷贝和销毁时执行的操作,一般不需要自行定义。
比如定义了一个Person类,则Person p1;Person p2;p1=p2;,这个=号我们在函数中并没有手动的对它进行定义但是却可以使用就是编译器自动生成的效果。
 
11.private的意思是该类的成员只能被类的成员函数访问,类的对象不能对其进行调用。public则是都可以对其进行调用。
我们可以在类的内部使用friend声明友元函数,如果将一个函数声明为了类的友元函数,那么在这个函数的内部就可以访问到这个类的private私有成员了。
struct Person
{
    friend int getAge(Person p);//声明友元函数
    Person();
    Person(string name,int age);
    string Name="maycpou";
    string getName();  
    private:
    int Age = 0;
};
int getAge(Person p){//友元函数的定义
    return p.Age;//访问类的私有成员
}
string Person::getName(){
    return this->Name;
}
Person::Person()=default;
Person::Person(string name,int age){
    this->Name = name;
    this->Age = age;
}
int main(int argc,char *argv[]){
    Person per("tttttt",111111);
    cout<<getAge(per)<<endl;
}
也可以将一个类或者这个类中的成员函数声明为另一个类的友元,同样声明为友元后类的成员函数就可以访问该类的私有成员了。
 
12.构造函数的简写方式:
struct Person{
  string Name;
  int Age;
  Person(string name,int age):Name(name),Age(age){}
}
上面的写法等价于:
struct Person{
  string Name;
  int Age;
  Person(string name,int age){
    this.Name = name;
    this.Age = age;
  }
}
 
13.c++11中新增加了一种新的构造函数的书写方式,委托构造函数。就是类中的一个构造函数委托给另一个构造函数来初始化。具体用法见博文C++11新特性
 
14.隐式的类类型转换
有一个Person类,它有一个一个string参数的构造函数。
有一个方法它的参数是一个Person类的对象
在调用这个方法的时候可以直接传入一个string类型的变量,他会自动去调用Person的那个一个string参数的构造函数,构造一个Person的对象作为参数传入。
注意:这种隐式转换只允许次转换,如上面的例子,我们调用方法的时候必须传入一个string的对象,而不能直接传入“maycpou”这种字符串,因为在引号字符串与string之间还存在一个隐式转换,在这里就不可用了。
struct Person
{
    Person()=default;
    string Name="maycpou";
    Person(string name,int age):Name(name),Age(age){};
    Person(string name):Name(name){};
    private:
    int Age = 0;
};

void getPersonName(Person p){
    cout<<p.Name<<endl;
}

int main(int argc,char *argv[]){
    string name = "tebiri";
    getPersonName(name);
}
如果不希望自己写的构造函数可以通过上面的方式隐式转换,可以在构造函数前面加上expicit关键字。
 
15.当一个类中没有任意的构造函数,都是public的成员时可以使用花括号{}来对类进行初始化:
struct Person
{
    string Name="fffffff";
    int age;
};
int main(int argc,char *argv[]){
    Person p{"aaa",12};

    cout<<p.Name<<endl;
}
 
posted @ 2021-03-08 16:57  maycpou  阅读(414)  评论(0编辑  收藏  举报