C++入门知识点总结

一、C++中的命名空间

C++中使用命名空间来解决在相同文件或范围的同名变量问题,示例程序如下:

#include <iostream>
using namespace std;

#if 0
int g_count = 100;

int g_count = 200;  //error,重命名错误
#endif

namespace stuname   //定义命名空间stuname
{
    const char *name = "zhangsan";  //定义命名空间中stuname的变量name
}

namespace homename   //定义命名空间homename
{
    const char *name = "xiaozhang";  //定义命名空间中homename的变量name
}

int main()
{
    cout << "school : " << stuname::name << endl;   //访问stuname命名空间中的数据

    cout << "homename : " << homename::name << endl;   //访问homename命名空间中的数据
}

二、C++标识符声明使用的三种方法

C++的所有标识符都被定义在一个名叫std的namespace(命名空间)里,要想使用这些标识符,则必须先声明,声明有以下3种方法:

int main()
{
     #if 0   //第1种:直接声明使用
        std::cout<<"hello world"<<std::endl;
     #endif
 
    #if 0   //第2种:先用using声明要使用的标识符
        using   std::cout;
        using   std::endl;
         cout<<"hello world"<<endl;
     #endif
 
     #if 1   //第3种:声明使用标准命名空间中所有内容(即标识符)
         using   namespace   std;    //一般申明在头文件后
         cout<<"hello world"<<endl;
     #endif
 
     return  0;
}

三、自动类型转换的四种情况

在C/C++中有以下四种情况会发生自动类型转换:

#include <iostream>
#include <stdlib.h>
#include <string.h>

using namespace std;

int add(double  num1,double num2)
{
    return  num1+num2;
}

int main()
{
    //第1种:赋值
    int i = 3.14;   //转换成int型
    cout << "i=" << i << endl;

    //第2种:运算时
    double res = 4 + 3.14;  //4运算前转换成double型
    cout << "res=" << res << endl;

    //第3种: 函数调用实参与形参不一致时,自动转换成形参类型
    //第4种:当返回值类型与函数返回类型不一致时,自动转换成函数返回类型
    int result = add(2,3);  //2,3转换成double型,5再转换成int型
    cout << "result=" << result << endl;

    return  0;
}

四、引用的使用

引用就是某一变量(目标)的一个别名,对引用的操作与对变量的直接操作完全一样。

引用的声明方法:类别标识符 &引用名 = 目标变量名。

示例程序如下所示:

int a;
int &ra=a; //定义引用ra,它是变量a的引用,即别名。

说明:

  • &在此处不是取地址运算,而是标识作用。
  • 声明引用时,必须对其进行初始化。
  • 引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量的别名。
  • 声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,他本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。因此对引用求地址,就是对目标变量求地址。
  • 不能建立数组的引用,因为数组是一个由若干个元素组成的集合,所以无法建立一个数组的别名。

五、C++内联函数

C++中支持内联函数,其目的是为了提高函数的执行效率,使用关键字 inline 可将函数指定为内联函数,内联函数通常就是将它在程序中的每个调用点上“内联地”展开,假设我们将 max 定义为内联函数:

inline int max(int a, int b)
{
	return a > b ? a : b;
}

调用: cout<<max(a, b)<<endl;,在编译时展开为: cout<<(a > b ? a : b)<<endl;从而消除了把 max写成函数的额外执行开销。

C++ 语言的函数内联机制既具备宏函数的效率,又增加了安全性,而且可以自由操作类的数据成员。所以在 C++ 程序中,应该用内联函数取代所有宏函数,“断言 assert”恐怕是唯一的例外。


注意

  • 代码过长,多于3行,则编译器会忽略 inline 限定符。
  • 在类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。
  • 函数内不能有复杂结构,例如for循环和开关语句。

六、C++多态相关

1、虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错,错误提示为:

error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"

2、虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。


3、在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。且基类的析构函数必须是虚函数,否则会析构不完全。


4、友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调用虚拟成员函数来解决友元的虚拟问题。


5、C++多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数;形成多态必须具备三个条件:

  • 必须存在继承关系;
  • 继承关系必须有同名虚函数(其中虚函数是在基类中使用关键字Virtual声明的函数,在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数);
  • 存在基类类型的指针或者引用,通过该指针或引用调用虚函数;

6、父类的虚函数或纯虚函数在子类中依然是虚函数。有时我们并不希望父类的某个函数在子类中被重写,在 C++11 及以后可以用关键字 final 来避免该函数再次被重写。

例:

#include<iostream>

using namespace std;

class Base
{
    public:
        virtual void func()
        {
            cout<<"This is Base"<<endl;
        }
};

class _Base:public Base
{
    public:
        void func() final//正确,func在Base中是虚函数
        {
            cout<<"This is _Base"<<endl;
        }
};

class __Base:public _Base
{
/*    public://不正确,func在_Base中已经不再是虚函数,不能再被重写
        void func()
        {
            cout<<"This is __Base"<<endl;
        }*/
};

int main()
{
    _Base a;
    __Base b;
    Base* ptr=&a;
    ptr->func();
    ptr=&b;
    _Base* ptr2=&b;    ptr->func();
    ptr2->func();
}

/*
输出结果:

This is _Base
This is _Base
This is _Base
*/

如果不希望一个类被继承,也可以使用 final 关键字。

格式如下:

class Class_name final
{
    ...
};

则该类将不能被继承。


七、C++ 函数传递参数的三种方式

(1)值传递

当进行值传递时,就是将实参的值复制到形参中,而形参和实参不是同一个存储单元,所以函数调用结束后,实参的值不会发生改变。程序示例如下:

#include <iostream> 
using namespace std; 

void swap(int a,int b)
{
	int temp; 
	temp=a;
	a=b;
	b=temp;
	cout<<a<<","<<b<<endl; // 2,1
}

int main()
{
	int x=l; 
	int y=2; 
	swap(x,y);
	cout<<x<<", "<<y<<endl; // 1,2
	
	return 0;
}

(2)指针传递

当进行指针传递时,形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。这种方式还是 “值传递”,只不过实参的值是变量的地址而已。而在函数中改变的不是实参的值,而是实参地址所指向的变量的值。程序示例如下:

#include <iostream> 
using namespace std; 

void swap(int *a,int *b)
{
	int temp; 
	temp=*a;
    *a=*b;
	*b=temp;
	cout<<*a<<","«*b«endl; // 2,1
}

int main()
{
	int x=l; 
	int y=2; 
	
	swap(&x,&y); 	
	cout<<x<<","<<y<<endl; 2,1
	
	return 0;
}

也就是说,在进行函数调用时,不仅交换了形参的值,而且交换了实参的值。


(3)引用传递

实参地址传递到形参,使形参的地址取实参的地址,从而使形参与实参共享同一单元的方式。程序代码示例如下:

#include <iostream> 
using namespace std; 

void swap(int &a,int &b) 
{
	int temp; 
	temp=a; 
	a=b; 
	b=temp;
	cout<<*a<<","<<*b<<endl; // 2,1
}

int main()
{
	int x=l; 
	int y=2; 
	swap(x,y);
	cout<<x<<","<<y<<endl; // 2,1
	
	return 0;
}

原文地址:https://www.cnblogs.com/linuxAndMcu/p/10252971.html