学习笔记 | C++ | C++核心编程

C++核心编程

1.命名空间——避免名称冲突,更好地控制标识符的作用域

1.1 命名空间的创建及调用

//创建命名空间A
namespace A {
   
	int a = 10;
	//嵌套命名空间B
	namespace B {
   
		int a = 20;
	}
}
//命名空间只能全局范围内定义
//cout << "A::a : " << A::a << endl;

//可以随时把新的成员加入已有的命名空间中
namespace A {
   
	void func() {
   
		cout << "hello namespace!" << endl;
	}
}

void test() {
   
	cout << "A::a : " << A::a << endl;
	cout << "A::B::a : " << A::B::a << endl;
	A::func();
	//起别名
	namespace C = A::B;
	cout << "C::a : " << C::a << endl;
}

1.2 using声明

namespace A{
   
	int paramA = 20;
	int paramB = 30;
	void funcA(){
    cout << "hello funcA" << endl; }
	void funcB(){
    cout << "hello funcA" << endl; }
}

void test(){
   
	//1. 通过命名空间域运算符
	cout << A::paramA << endl;
	A::funcA();
	//2. using声明
	using A::paramA;
	using A::funcA;
	cout << paramA << endl;
	//cout << paramB << endl; //未声明,不可直接访问
	funcA();
	//3. 同名冲突
	//int paramA = 20; //相同作用域注意同名冲突
}

1.3 using编译指令

namespace A{
   
	int paramA = 20;
	int paramB = 30;
	void funcA(){
    cout << "hello funcA" << endl; }
	void funcB(){
    cout << "hello funcB" << endl; }
}

void test01(){
   
	using namespace A;
	cout << paramA << endl;
	cout << paramB << endl;
	funcA();
	funcB();

	//不会产生二义性
    //命名空间中的 paramA 是全局变量,这里的 paramA 是局部变量
	int paramA = 30;
	cout << paramA << endl;
}

namespace B{
   
	int paramA = 20;
	int paramB = 30;
	void funcA(){
    cout << "hello funcA" << endl; }
	void funcB(){
    cout << "hello funcB" << endl; }
}

void test02(){
   
	using namespace A;
	using namespace B;
	//二义性产生,不知道调用A还是B的paramA
	//cout << paramA << endl;
}

2.内联函数——在适当的地方像预定义宏一样展开,不需要函数调用的开销(空间换时间)

//函数体和声明结合在一起
inline int func(int a) {
    return a+1; }

class Person {
   
public:
	Person() {
    cout << "构造函数!" << endl; }
	//任何在类内部定义的函数自动成为内联函数
	void PrintPerson() {
    cout << "输出Person!" << endl; }
};

void test() {
   
	Person p;
	p.PrintPerson();
}

3.内存分区模型——数据存放的区域不同,生命周期不同,使编程更加灵活

在这里插入图片描述

3.1 程序运行前

​ 在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域

代码区:

​ 存放CPU执行的机器指令

​ 代码区是共享的,目的是对于频繁被执行的程序,只需要在内存中有—份代码即可

​ 代码区是只读的,原因是防止程序意外地修改了它的指令

全局区:

​ 全局变量和静态变量存放在此

​ 全局区还包含了常量区,字符串常量和其他常量也存放在此

该区域的数据在程序结束后由操作系统释放

在这里插入图片描述

3.2 程序运行后

栈区:

​ 由编译器自动分配释放,存放函数的参数值,局部变量等

​ 注意事项:不要返回局部变量,栈区开辟的数据由编译器自动释放

堆区:

​ 由程序员分配释放,若程序员不释放,程序结束时由操作系统回收

在C++中主要利用new在堆区开辟内存

int * func() {
   
    //利用new关键字 可以将数据开辟到堆区
    int* p = new int(10);
    return p;
}

void test02() {
   
    //创建10整型数据的数组,在堆区
    int * arr = new int[10];
    for (int i = 0; i < 10; i++) {
   
        arr[i] = i + 100;
    }
    //首地址
    cout << arr << endl;
    for (int i = 0; i < 10; i++) {
   
        cout << arr[i] << "   " << &arr[i] << endl;

    }
    //释放内存
    delete[] arr;
}

int main() {
   
    int* p = func();
    cout << *p << endl;
    //释放内存用delete
    delete p;
    test02();
}

4.引用——给变量起别名

4.1 引用的使用

int main() {
   
    int a = 10;
    //使用引用
    int& b = a;
    cout << "a=" << a << endl;
    cout << "b=" << b << endl;
    b = 100;
    cout << "a=" << a << endl;
    cout << "b=" << b << endl;
    return 0;
}

4.2 引用做函数参数

  • 函数传参时,可以利用引用的技术让形参修饰实参

    //引用传递_效果同地址传递
    void swapaa(int& a, int& b) {
         
        int temp = a;
        a = b;
        b = temp;
    }
    
    int main() {
         
        int a = 10;
        int b = 20;
        swapaa(a, b);
        cout << a << endl;
        cout << b << endl;
        return 0;
    }
    

4.3 引用做函数返回值

//引用做函数的返回值
//1.不要返回局部变量引用
int& test01() {
   
    int a = 10;//a为局部变量(栈区)
    return a;
}
//2.函数的调用可以作为左值
int& test02() {
   
    static int a = 20;//a为静态变量(全局区)
    return a;
}
int main() {
   
    int& ref = test01();

    cout << "ref  " << ref << endl;
    cout << "ref  " << ref << endl;
   
    int& ref2 = test02();
    cout << "ref2  " << ref2 << endl;
    cout << "ref2  " << ref2 << endl;
    //如果函数的返回值时引用,这个函数调用可以做左值
    test02() = 1000;//a = 1000;
    cout << "ref2  " << ref2 << endl;
    cout << "ref2  " << ref2 << endl;
    return 0;
}

在这里插入图片描述

4.4 引用的本质

  • 引用的本质在C++内部实现是一个指针常量int * const p = &a;、

    //发现是引用,转换为int* const ref = &a;
    void func(int& ref) {
         
    	ref = 100;//ref是引用,转换为* ref = 100
    }
    int main() {
         
    	int a = 10;
    
    	//自动转换为 int*const ref = &a;指针常量是指针指向不可改,也说明为什么引用不可更改
    	int& ref = a;
    	ref = 20;//内部发现ref是引用,自动帮我们转换为:*ref = 20;
    
    	cout << "a:" << a << endl;
    	cout << "ref : " << ref << endl;
    
    	func(a);
    	return 0;
    }
    

4.5 常量引用

  • 常量引用主要用来修饰形参,防止误操作

    //引用使用的场景,通常用来修饰形参
    void showValue(const int& v) {
         
    	//v += 10;
    	cout << v << endl;
    }
    int main() {
         
    	//int& ref = 10;	//错误,引用本身需要一个合法的内存空间
    	//加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;(注意会附加const属性)
    	const int& ref = 10;
    
    	//ref = 100;	//加入const后不可以修改变量
    	cout << ref << endl;
    
    	//函数中利用常量引用防止误操作修改实参
    	int a = 10;
    	showValue(a);
    	return 0;
    }
    

5.函数提高

5.1 函数的默认参数

//返回值类型 函数名 (参数= 默认值){}
int func(int a,int b = 10){
   
	return a+b;
}
//1.如果某个位置已经有了默认参数,那么从这个位置往后都必须有默认值
int func2(int a = 10,int b){
   
	return a+b;
}
//2.如果函数声明中有默认参数,函数实现就不能有默认参数
//出现二义性导致错误
int func2(int a = 10,int b = 10);
int func2(int a = 10,int b = 10){
   
    return a + b;
}

5.2 函数占位参数

//函数占位参数,占位参数也可以有默认参数
void func(int a, int = 10) {
   
    cout << "this is func" << endl;
}
int main() {
   
    func(20);//占位参数必须填补
    return 0;
}

5.3 函数重载

//同一个作用域下,函数名相同,参数类型不同 或者 个数不同 或者 顺序不同
void func() {
   
	cout << "func 的调用" << endl;
}
void func(int a) {
   
	cout << "func(int a)的调用" << endl;
}
void func(double a) {
   
	cout << "func(double a)的调用" << endl;
}
void func(int a, double b) {
   
	cout << "func(int a, double b)的调用" << endl;
}
int main() {
   
	int a = 10;
	double b = 20.5;
	func();
	func(a);
	func(b);
	func(a, b);
	return 0;
}

6.类和对象——C++面向对象的三大特征:封装、继承、多态

6.1 封装

  • 将属性和行为作为一个整体,表现生活中的事物
class 类名{
    访问权限:属性/行为};

//示例(圆):
//圆周率
const double PI = 3.14;

//创建一个对象的类
class Circle {
   
	public: //访问权限 公共的权限
		int m_r;//半径

		//行为
		//获取到圆的周长
		double calculateZC() {
   
			//获取圆的周长
			return 2 * PI * m_r;
		}
};
int main() {
   
	//通过圆类,创建圆的对象
	//c1就是一个我们创造的圆
	Circle c1;
	c1.m_r = 10;
	cout << "圆的周长为: " << c1.calculateZC() << endl;
	return 0;
}
  • 将属性和行为加以权限控制
//三种权限
//公共权限 public 		类内可以访问	类外可以访问
//保护权限 protected	类内可以访问	类外不可以访问	儿子可以访问父亲中的保护内容
//私有权限 private		类内可以访问	类外不可以访问	儿子不可以访问父亲中的私有内容

class Person {
   
public: //公共权限
	string m_name;//姓名
protected://保护权限
	string m_car;//汽车
private://私有权限
	int m_password;//密码
public:
	void func() {
   //类内访问
		m_name = "张三";
		m_car = "摩托";
		m_password = 123456;
	}
};

int main() {
   
	//实例化对象
	Person p1;
	
	p1.m_name = "李四";
	p1.m_car = "汽车";//错误,不可访问
	p1.m_password = 654321;//错误,不可访问
	return 0;
}
  • struct和class的区别
唯一区别:
//struct 默认权限为公共
//class 默认权限为私有
  • 将成员属性设置为私有
//优点1:将成员属性设置为私有,可以自己控制读写权限
//优点2:对于权限,我们可以检测数据的有效性
class Person {
   
private:
	//可读可写
	string m_name;
	//只读
	int m_age;
	//只写
	string m_lover;
public:
	void setname(string name) {
   
		m_name = name;
	}
	string getname() {
   
		return m_name;
	}
	int getage() {
   
		m_age = 0;
		return m_age;
	}
	void setlover(string lover) {
   
		m_lover = lover;
	}
};

int main() {
   
	//实例化对象
	Person p1;
	
	p1.setname("张三");
	p1.setlover("李四");
	cout << "姓名为:" << p1.getname() << endl;
	cout << "年龄为:" << p1.getage() << endl;
	return 0;
}

6.2 对象的起始化和清理

6.2.1 构造函数和析构函数
 //构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动
 //析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作
  • 构造函数

    1. 构造函数,没有返回值也不写void

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值