在这里推荐一个博主写的C++笔记非常全面非常好,适合写的时候查:地址连接
今日看了C++的基础语法,C++是在C的基础上进行功能的扩充,由于本人有C语言基础,所以学起来相较容易,以下为在学习C++过程中需要特殊记忆以及与所使用的其他语言区别起来的点。
1.类的定义
C++与python一样在类内使用与类名称相同的函数作为构造函数,并且可以有多个同名的构造函数,通过形参的个数不同来区分进行重载。可以预初始化类的参数,并且C++可以在定义类中的方法的时候不写方法的内容,在外部使用“::”定义类的内容,构造函数也可以外部定义,注意构造函数没有返回值所以不需要在函数名前加返回值类型或者void。
class Box
{
public:
Box(double a = 0,double b = 0,double c = 0)
{
this->a = a;breadth = b;height = c;
}
// 成员函数声明
double get(void);
private:
double a; // 长度
double breadth; // 宽度
double height; // 高度
};
// 成员函数定义
double Box::get(void)
{
return a * breadth * height;
}
2.类和函数的继承
本人笨拙的认为在C++语言中把“:“认为是继承的标志
class Rectangle: public Shape,public Light{...}//此为类的继承
Rectangle(int a=0,int b=0):Shape(a, b) { }//此为Rectangle的构造函数继承shape类的构造函数
访问控制和继承:
访问 | public | protected | private |
---|---|---|---|
同一个类 | yes | yes | yes |
派生类(子类) | yes | yes | no |
外部的类 | yes | no | no |
3.多态与重构运算符
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。在子类中如果需要重构父类中的某个函数,在父类中的这个函数需要定义为虚函数,即在前加入关键字“virtual”,如果在父类中不适用虚函数的话,调用子类的该函数的话会产生静态链接(早绑定),默认调用父类的该函数。
多态在python中则不一样,父类和子类同名函数直接做区分,只会使用调用类的同名函数。
在这里再提一句纯虚函数,您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。
virtual int area() = 0;//用“virtual”和“=0”来标识
在类内重构运算符:
//重载运算符+
retun_type operator+(const Box&,......);
class Box
{
public:
double getVolume(void)
{
return length * breadth * height;
}
void setLength( double len )
{
length = len;
}
void setBreadth( double bre )
{
breadth = bre;
}
void setHeight( double hei )
{
height = hei;
}
// 重载 + 运算符,用于把两个 Box 对象相加
Box operator+(const Box& b)
{
Box box;
box.length = this->length + b.length;
box.breadth = this->breadth + b.breadth;
box.height = this->height + b.height;
return box;
}
private:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
4.命名空间
可以将命名空间抽象成一个一个文件夹,文件夹可以有包含关系,使用一个namespace则代表在这个文件夹下添加数据。
命名空间的定义使用关键字 namespace,后跟命名空间的名称:
namespace namespace_name {// 代码声明}
为了调用带有命名空间的函数或变量,需要在前面加上命名空间的名称:
name::code; // code 可以是变量或函数
您可以使用 using namespace 指令,这样在使用命名空间时就可以不用在前面加上命名空间的名称。这个指令会告诉编译器,后续的代码将使用指定的命名空间中的名称。相当于在using namespace后就可以不用再::说明用的是哪个命名空间内的内容。
命名空间可以嵌套,您可以在一个命名空间中定义另一个命名空间,并使用::访问内部空间:
namespace namespace_name1 {
// 代码声明
namespace namespace_name2 {
// 代码声明
}
}
// 访问 namespace_name2 中的成员
using namespace namespace_name1::namespace_name2;
5.内联函数
具体不是特别深究过,在C与C++中均有使用,作用大概是,在函数体量很小的时候,执行函数之前的准备相对于执行函数所消耗的时空占比很大,显得没必要。为了消除函数调用的时空开销,C++ 提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开。这种在函数调用处直接嵌入函数体的函数称为内联函数(Inline Function),又称内嵌函数或者内置函数。相当于一种对于小体量函数的高效运行替换。
6.C++模板,用"<>"标识
这是个好东西,但是一开始不太好理解。比如说,需要写一个函数,交换两个数据的内容,如果用函数来写的话,如果需要交换的两个数据是int型或者char型或者long型的话需要写三个函数来实现,更多其他类型则需要写更多的函数。C++模板就是来解决这类问题的,值定义一个逻辑模板,传入的参数我们自己来定义。函数模板写法如下:
template <class 类型参数1, class类型参数2, ...>
返回值类型 模板名(形参表)
{
函数体
}
template <class T> //我理解的是相当于将参数类型当做参数传递,类模板也是如此
void Swap(T & x, T & y)
{
T tmp = x;
x = y;
y = tmp;
}
其中class也可以使用typename。这样就很好的解决了以上的问题。我应该是会使用typename,因为我认为这样更直观。
类模板写法如下:
template <typename T>
class Complex
{
public:
//构造函数
Complex(T a, T b)
{
this->a = a;
this->b = b;
}
//运算符重载
Complex operator+(Complex& c)
{
Complex tmp(this->a + c.a, this->b + c.b);//直接在这里初始化
return tmp;
}
private:
T a;
T b;
};
7.Lambda表达式
对于代码体量小,无复用的一定功能的函数处理后用作参数传递,直接传递函数体可以增加代码的可读性。但是理解起来有些困难。
Lambda语法如下:
(1)捕获列表。在C ++规范中也称为Lambda导入器, 捕获列表总是出现在Lambda函数的开始处。实际上,[]是Lambda引出符。编译器根据该引出符判断接下来的代码是否是Lambda函数,捕获列表能够捕捉上下文中的变量以供Lambda函数使用。而且正常捕获的变量只可读,若要更改无效,如果用标志“&”使用引用捕获可以改变捕获变量的值。
(2)参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号“()”一起省略。
(3)可变规格*。mutable修饰符, 默认情况下Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空)。*
(4)异常说明。用于Lamdba表达式内部函数抛出异常。这里还有待补充。
(5)返回类型。 追踪返回类型形式声明函数的返回类型。我们可以在不需要返回值的时候也可以连同符号”->”一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导。
(6)lambda函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。
8.C++预处理器
(1)参数宏
#define MIN(a,b) (a<b ? a : b)
(2)条件编译
有几个指令可以用来有选择地对部分程序源代码进行编译。这个过程被称为条件编译。
#ifdef NULL
#define NULL 0
#endif
#ifdef DEBUG
cerr <<"Variable x = " << x << endl;
#endif
#if 0
不进行编译的代码
#endif
(3)C++ 提供了下表所示的一些预定义宏
宏 | 描述 |
---|---|
__LINE__ | 这会在程序编译时包含当前行号。 |
__FILE__ | 这会在程序编译时包含当前文件名。 |
__DATE__ | 这会包含一个形式为 month/day/year 的字符串,它表示把源文件转换为目标代码的日期。 |
__TIME__ | 这会包含一个形式为 hour:minute:second 的字符串,它表示程序被编译的时间。 |
#include <iostream>
using namespace std;
int main ()
{
cout << "Value of __LINE__ : " << __LINE__ << endl;
cout << "Value of __FILE__ : " << __FILE__ << endl;
cout << "Value of __DATE__ : " << __DATE__ << endl;
cout << "Value of __TIME__ : " << __TIME__ << endl;
return 0;
}
output:
Value of __LINE__ : 6
Value of __FILE__ : test.cpp
Value of __DATE__ : Feb 28 2011
Value of __TIME__ : 18:52:48
9.友元函数“frend”
在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术。友元分为三种:
(1)全局函数做友元
class Building
{
// 告诉编译器 laoWang全局函数是 Building类 的好朋友,可以访问Building对象的私有成员
//此下为三个全局函数
friend void laoWang1(Building *building);
friend void laoWang2(Building &building);
friend void laoWang3(Building building);
public:
Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
string m_SittingRoom; // 客厅
private:
string m_BedRoom; // 卧室
};
(2)类做友元
class Building
{
// 告诉编译器,LaoWang类是Building类的好朋友,可以访问Building类的私有成员
//类LaoWang的实例可以访问Building的私有变量
friend class LaoWang;
public:
Building();
string m_SittingRoom; // 客厅
private:
string m_BedRoom; // 卧室
};
(3)成员函数做友元
class Building
{
// 告诉编译器,LaoWang类下的visit1()函数是Building类的好朋友,可以访问Building的私有成员
//类LaoWang的成员函数可以访问Building的私有成员
friend void LaoWang::visit1();
public:
Building();
string m_SittingRoom; //客厅
private:
string m_BedRoom; //卧室
};