一、命名空间
standard:标准命名空间
using namespace std;
命名空间类似于java中的包。
- 自定义命名空间
namespace NSP_A{
int a = 9;
struct Teacher{
char name[20];
int age;
};
struct Student{
char name[20];
int age;
};
}
namespace NSP_B{
int a = 12;
//命名空间嵌套
namespace NSP_C{
int c = 90;
}
}
- 使用命名空间
cout << NSP_A::a << endl;
cout << NSP_B::a << endl;
cout << NSP_B::NSP_C::c << endl;
//使用命名空间中的结构体
using NSP_A::Student;
Student t;
t.age = 90;
::
为访问修饰符
二、引用
引用是变量的别名(内存空间0x00001的别名),指针是变量的地址
int a = 10;
// b是内存空间的另一个别名
//& C++中的引用
int &b = a;
- 使用指针交换数据
void swap(int *a, int *b){
int c = 0;
c = *a;
*a = *b;
*b = c;
}
- 使用引用交换数据
void swap(int &a, int &b){
int c = 0;
c = a;
a = b;
b = c;
}
引用的主要功能:作为函数的参数或返回值,引用必须有值,不能为空
单纯给变量取别名没有任何意义,作为参数传递,能保证参数传递过程中不产生副本;
引用可以直接操作变量,指针要通过取值(*p),间接操作变量,指针的可读性差。
- 指针的引用代替二级指针
struct Teacher{
char* name;
int age;
};
void getTeacher(Teacher **p){
Teacher *tmp = (Teacher*)malloc(sizeof(Teacher));
tmp->age = 20;
*p = tmp;
}
//代替二级指针
//Teacher* &p = (Teacher * *p)
void getTeacher(Teacher* &p){
p = (Teacher*)malloc(sizeof(Teacher));
p->age = 20;
}
- 指针常量/常量指针
指针常量
:不改变地址的指针,但是可以修改指针指向的内容
int a = 2, b = 3;
int *const p = &a;
p = &b; //不能重新赋值
*p = 4; 可以改变指向的内容
常量指针
:指向常量的指针,内容不能修改
const int *p = &a;
p = &b;
//*p2 = 9; //不能改变内容
三、函数
- C++中函数可以有默认值
void customPrint(int x, int y = 9, int z = 8){
cout << x << endl;
}
- 可变参数
#include <stdarg.h>
void func(int i,...){
// 可变参数指针
va_list args_p;
// 开始读取可变参数类型,i是最后一个固定参数
va_start(args_p,i);
int a = va_arg(args_p,int);
char b = va_arg(args_p, char);
int c = va_arg(args_p, int);
cout << a << endl;
cout << b << endl;
cout << c << endl;
va_end(args_p);
}
void func(int i,...){
va_list args_p;
va_start(args_p,i);
int value;
// 可变参数必须是相同类型
while (1) {
value = va_arg(args_p,int);
if (value <= 0){
break;
}
cout << value << endl;
}
va_end(args_p);
}
四、类
- 定义头文件
#pragma once
class Person{
public:
int age;
char* name;
public:
void setAge(int age);
int getAge();
void setName(char* name);
char* getName();
};
- 实现头文件定义的函数
#include "Person.h"
void Person::setAge(int age){
this->age = age;
}
int Person::getAge(){
return this->age;
}
void Person::setName(char* name){
this->name = name;
}
char* Person::getName(){
return this->name;
}
- 使用类
#include "Person.h"
void main(){
Person person;
person.name= "Jack";
}
- 构造函数
class Person{
private:
char *name;
int age;
public:
//无参改造函数(会覆盖默认的无参构造函数)
Person(){
cout << "无参构造函数" << endl;
}
// 有参构造
Person(char *name, int age){
this->name = name;
this->age = age;
cout << "有参构造函数" << endl;
}
};
- 析构函数
当对象要被系统释放时析构函数会被调用
~Person(){
cout << "析构函数" << endl;
//释放内存
free(this->name);
}
- 拷贝构造函数
class Person{
private:
char *name;
int age;
public:
Person(char *name, int age){
this->name = name;
this->age = age;
cout << "有参构造函数" << endl;
}
//拷贝构造函数
//默认的拷贝构造函数是值拷贝,拷贝的是指针地址
Person(const Person &obj){
this->name = obj.name;
this->age = obj.age;
cout << "拷贝构造函数" << endl;
}
};
void main(){
Person p1("Jack",20);
Person p2 = p1;
}
输出结果:
有参构造函数
拷贝构造函数
- 深拷贝
覆盖默认的拷贝构造函数,拷贝的是指针指向的内容
Person(const Person &obj){
//复制name属性
int len = strlen(obj.name);
this->name = (char*)malloc(len+1);
strcpy(this->name,obj.name);
this->age = obj.age;
}
拷贝构造函数被调用的场景:
- 声明时复制
- 最为参数传入,实参给形参赋值
- 作为函数返回值返回,给变量初始化赋值
- 构造函数的属性初始化列表
class Teacher{
private:
char* name;
public:
Teacher(char* name){
this->name = name;
}
~Teacher(){
cout << "析构函数" << endl;
}
char* getName(){
return this->name;
}
};
class Student{
private:
int id;
//属性对象
//Teacher t = Teacher("name");
Teacher t1;
Teacher t2;
public:
Student(int id,char *t1_n, char* t2_n) : t1(t1_n), t2(t2_n){
this->id = id;
cout << "Student构造函数" << endl;
}
~Student(){
cout << "Student析构函数" << endl;
}
};
五、new/delete动态内存分配
void func(){
//C++
//会调用构造函数和析构函数
Teacher *t1 = new Teacher("jack");
cout << t1->getName() << endl;
//释放
delete t1;
//C的写法,不会调用构造函数和析构函数
//Teacher *t2 = (Teacher*)malloc(sizeof(Teacher));
//t2->setName("jack");
//free(t2);
}
数组类型
//C
//int *p1 = (int*)malloc(sizeof(int) * 10);
//p1[0] = 9;
//free(p1);
//C++
int *p2 = new int[10];
p2[0] = 2;
//释放数组要加上 []
delete[] p2;
六、静态属性、静态方法
class Teacher{
public:
char* name;
//静态成员
static int total;
public:
Teacher(char* name){
this->name = name;
cout << "Teacher构造函数" << endl;
}
}
静态属性初始化赋值
int Teacher::total = 9;
初始化完成后使用
Teacher::total++;
静态函数
static void count(){
total++;
cout << total << endl;
}
调用静态函数
Teacher::count();
七、类的大小
class A{
public:
int i;
int j;
int k;
};
class B{
public:
int i;
int j;
int k;
void fun(){
cout << "fun" << endl;
}
};
int main(int argc, const char * argv[]) {
cout<< sizeof(A)<<endl;
cout<< sizeof(B)<<endl;
return 0;
}
输出结果:
12
12
C/C++内存分区:栈、堆、全局(静态)、常量去(字符串)、程序代码区
普通属性与结构体相同的内存布局
静态变量存储在全局区
函数存在程序代码区
八、友元函数
class A{
//友元函数
friend void modify_i(A *p, int a);
private:
int i;
public:
A(int i){
this->i = i;
}
};
//友元函数的实现,在友元函数中可以访问私有的属性
void modify_i(A *p, int a){
p->i = a;
}
九、友元类
class A{
//友元类
friend class B;
private:
int i;
public:
A(int i){
this->i = i;
}
};
class B{
public:
//友元类可以访问A中的任何成员
void accessAny(){
a.i = 30;
}
private:
A a;
};
十、运算符重载
class Point{
public:
int x;
int y;
public:
Point(int x = 0, int y = 0){
this->x = x;
this->y = y;
}
void myprint(){
cout << x << "," << y << endl;
}
//成员函数运算符重载
Point operator+(Point &p2){
Point tmp(this->x + p2.x, this->y + p2.y);
return tmp;
}
};
//重载+运算符
Point operator+(Point &p1, Point &p2){
Point tmp(p1.x + p2.x, p1.y + p2.y);
return tmp;
}
//重载-运算符
Point operator-(Point &p1, Point &p2){
Point tmp(p1.x - p2.x, p1.y - p2.y);
return tmp;
}
十一、继承
class Human{
public:
void say(){
cout << "say" << endl;
}
protected:
char* name;
int age;
};
//子类
class Man : public Human{
public:
void work(){
cout << "work" << endl;
}
private:
char* brother;
};
int main(int argc, const char * argv[]) {
Man man;
man.say();
Human *p = &man;
p->say();
return 0;
}
带有参构造函数的继承
class Human{
public:
Human(char* name, int age){
this->name = name;
this->age = age;
}
void say(){
cout << "say" << endl;
}
protected:
char* name;
int age;
};
class Man : public Human{
public:
Man(char *brother, char *s_name, int s_age, char *h_name, int h_age) : Human(s_name, s_age), h(h_name,h_age){
this->brother = brother;
}
void work(){
cout << "work" << endl;
}
private:
char* brother;
Human h;
};
多继承
//人
class Person{
};
//公民
class Citizen{
};
//多继承
class Student : public Person, public Citizen{
};
十二、多态
- 虚函数实现多态
//Plane.h
class Plane{
public:
virtual void fly();
virtual void land();
};
//Plane.cpp
void Plane::fly(){
cout << "起飞" << endl;
}
void Plane::land(){
cout << "着陆" << endl;
}
// Helicopter.h
class Helicopter : public Plane{
virtual void fly();
virtual void land();
};
// Helicopter.cpp
void Jet::fly(){
cout << "直升机起飞" << endl;
}
void Jet::land(){
cout << "直升机着陆" << endl;
}
- 纯虚函数(抽象类)
当一个类具有纯虚函数时,这个类就是抽象类。抽象类不能实例化对象。子类继承抽象类必须实现纯虚函数,如果没有子类也是抽象类
class Shape{
public:
//纯虚函数
virtual void sayArea() = 0;
};
class Circle : public Shape{
public:
Circle(int r){
this->r = r;
}
void sayArea(){
cout << "圆的面积" << (3.14 * r * r) << endl;
}
private:
int r;
};
十三、模板函数(泛型)
void myswap(int& a,int& b){
int tmp = 0;
tmp = a;
a = b;
b = tmp;
}
void myswap(char& a, char& b){
char tmp = 0;
tmp = a;
a = b;
b = tmp;
}
上面两个函数业务逻辑一样,数据类型不一样。
template <typename T>
void myswap(T& a, T& b){
T tmp = 0;
tmp = a;
a = b;
b = tmp;
}
网友评论