C++ 基础知识(二)

1.复制构造函数

编译器会默认提供复制拷贝函数,但是也可以显式的定义,形参是本类对象的引用

class point
{
private :
    int a;
    int b;
public:
    point(int x,int y)
    {
        a=x;
        b=y;
        std::cout<<"调用构造函数"<<std::endl;
    }
    point(const point& p)      //显式的定义复制构造函数,必须是按引用传参&的形式,const可以不加,最好加
    {
        std::cout<<"调用复制构造函数"<<std::endl;
        a=p.a;
        b=p.b;
    }
    print()
    {
        std::cout<<a<<b<<std::endl;
    }
};
int main()
{
    point p1(3,5);     
    point p2=p1;        //可以通过直接赋值的方式,这样会调用复制构造函数  
    p2.print();
    
    point p2(p1);      //也可以通过参数传参的方式,与上面的等价
    p2.print();
    return 0;
}

有些时候必须显式的定义复制构造函数,比如类中含有指针类的数据成员、需要使用动态内存,最好定义复制构造函数,避免内存错误

 

2.友元
友元函数:

下面的例子通过友元函数来访问类内部私有成员,该友元函数不属于任何一个类

class point
{
private :
    int a;
    int b;
public:
    point():a(3),b(4)
    {

    }
    show_ab();
    friend void show_ab_f(point &p);   //声明友元函数
    int c=5;
};

point::show_ab()
{
   std::cout<<a<<b<<std::endl;          //成员函数访问私有对象
}

void show_ab_f(point &p)                //定义友元函数,此函数不属于任何类
{
   std::cout<<p.a<<p.b<<std::endl;      //友元函数访问私有对象
}

int main()
{
    point p;
    p.show_ab();                         //调用成员函数 
    show_ab_f(p);                        //调用友元函数,传入point类
    std::cout<<p.a<<p.b<<std::endl;      //报错,私有对象只能类成员访问
    std::cout<<p1.c<<std::endl;          //只能访问共有对象
    return 0;
}

上面的例子是一个全局函数为point的友元函数,也可以定义一个类的成员函数为另一个类(point)的友元函数

那么该函数既可以访问本类的成员,也可以访问类point的成员,这里就不写例子了

 

友元类:

友元类,就是一个类(line)是另一个类(point)的友元类,那么友元类(line)的所有成员函数都可以访问point类的所有成员,如下例:

class  line;   //先声明line类,后面在定义,不然下面point类中不认识line
class point
{
private :
    int a;
    int b;
    friend line;    //声明友元类
public:
    point():a(3),b(4)
    {
    }
};
class line  //定义line类
{
public:
    show(point& p)
    {
        std::cout<<p.a<<p.b<<std::endl;  //访问point的成员
    }
};
int main()
{
    point p;
    line _line;
    _line.show(p);
    return 0;
}

 

 

3.内联函数(inline)

内联函数就是在函数定义前加上inline关键字的函数。
例如A函数调B函数,B函数是内联函数,则编译器会把B函数的函数体复制到A函数里面,A函数里包含了B函数的代码,而B函数则不存在了,从而节省反复调用的函数开销

为什么要用inline?

假设有下列min()函数

int min( int v1, int v2 )  
{  
    return( v1 < v2 << v1 : v2 );  
}

 为这样的小操作定义一个函数的好处是:

  • 如果一段代码包含min()的调用,那阅读这样的代码并解释其含义比读一个条件操作符的实例,可读性会强很多。
  • 改变一个局部化的实现比更改一个应用中的300个出现要容易得多
  • 语义是统一的,每个测试都能保证相同的方式实现
  • 函数可以被重用,不必为其他的应用重写代码 

不过,将min()写成函数有一个严重的缺点:如果程序中有很多地方频繁的调用min函数,这样的话,比直接计算条件操作符要慢很多。为什么?

假设A函数中调用了B函数,在调用B函数时,先要中断A函数,将执行流程转移到B函数中,等B函数执行完,再返回A函数,所以在调用B函数前,要保护A函数的现场,记录程序当前位置,以方便从B函数返回,恢复现场,并从原来的位置继续执行. 如果频繁调用,则会影响程序性能
inline 函数正是为了解决这个问题的。总结下:
(1)inline函数就是以空间换时间,是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率
(2)inline函数必须在函数定义前加 inline关键字,声明前加则不起作用
(3)对于像一些短小,调用频繁的函数可以使用inline。对一些很长的函数,或者包含循环,switch,递归的函数不要使用inline。
(4)inline对于编译器来说只是一个建议,编译器可以选择忽略该建议。换句话说,哪怕真的写成了inline, 而且没有错误,编译器也会自动进行优化。所以当inline中出现了递归,循环,或过多代码时,编译器自动无视inline声明,同样作为普通函数调用

 

4.函数的重载
一个函数有相同的名字,但是传参的形式和返回值不一样,则视为函数的重载
不能出现名字相同,传参相同,仅仅是返回值不同的重载,编译器会报错。
 

5.继承
(1).基类和派生类:B类继承自 A类,则A类称为基类,B类称为派生类
(2)直接基类和间接基类。 举例孙子继承父亲,父亲继承爷爷。父亲是孙子的基类,也称为直接基类,爷爷是父亲的直接基类。而爷爷是孙子的间接基类。
(3)public继承,protect继承,private继承
public、protected、private方式继承后,成员属性的变化如下表:

(4)多基派生和单基派生
单基派生就是指 派生类只有一个基类。
多基派生就是指 派生类有多个基类,既同时继承多个基类,C++ 支持多继承


 

 

posted @ 2018-12-09 00:00  birdhumen鸟人  阅读(170)  评论(0编辑  收藏  举报