【C++】1.基本结构,面向对象,与c的区别,作用域,命名空间,using,引用

这篇博客详细介绍了C++的基础知识,包括头文件的使用、命名空间的作用、面向对象的三大特性(封装、继承、多态)、C++对C语言的增强如全局变量和函数检测、引用的概念和应用,以及参数传递的三种方式(值传递、地址传递和引用传递)。重点强调了C++中的const用法、引用的本质和注意事项,并提倡使用const替代#define。此外,还探讨了如何避免命名冲突和使用命名空间。
摘要由CSDN通过智能技术生成

1、基本结构

#include <iostream>//标准输入输出流,in输入,out输出
using namespace std;//使用命名空间 std表示打开一个叫std的房间
int main(){}//函数入口地址
cout << "hello world" <<endl//cout:标准的输出,在iostream头文件里,cout在std里;<<左移运算符,符号重载,在这里是拼接作用;endl:输出换行并刷新缓冲区
std:: cout << "hello world" <<endl//如果不打开std房间的写法.::作用域,std的作用域
system("pause");//请按任意键继续。。阻塞功能
return EXIT_SUCCESS//成功离开返回0,正常退出

2、c++头文件没有.h

(1)为什么c++头文件没有.h?
include <cmath>
include <>

3、面向对象三大特性

(1)封装
将成员封装在类中
(2)继承
类与类之间的关系
(3)多态
一个接口,多种方法

4、调用传统c库的方法

#define _CRT_SECURE_NO_WARINGS

5、双冒号作用域运算符

int atk=200; //全局变量  
void test01(){  
    int atk=100;  
    cout<<"test中的"<<atk<<endl;  //输出100
    cout<<"全局中的"<<::atk<<endl; //输出200
}
int main(){  
    cout << atk <<endl;  //输出200
    test01();  
}

双冒号,作用域运算符-> ::全局作用域

6、namespace的使用

命名空间主要是用来解决命名冲突的问题.
命名空间下可以放函数、变量、结构体、类;
命名空间必须定义在全局作用域下;
命名空间可以嵌套命名空间;
命名空间是开放的,可以随时往原先的命名空间添加内容;
可以有无名/匿名命名空间;

namespace {  
    int c=0;  
    int d=0;  
    //无名命名空间。相当于static int c = 0;  
    //只能在当前文件内使用  
}

命名空间可以起别名;

namespace veryLongName{
	int A=0;
}
void test04(){
	namespace veyShortName = veyLongName;
	cout<<veyShortName::A<<endl;
}

(1)新建头文件game1.h

#include <iostream>
using namespace std;
namespace LOL{
	void goAtk();
	int A;
	struct Person{
	};
	class Animal{};

	namespace B{
	int A=10; //写法是LOL::B::A
	}
}

(2)新建cpp文件game1.cpp

#include "game1.h"
void LOL::goAtk(){
	cout<<"LOL攻击"<<endl;
}

(3)在main.cpp中引入

#includ "game1.h"
using namespace LOL;

int main(){
	LOL::goAtk();
}

7、using声明和using编译指令

8、c++对c语言的增强

(1)全局变量检测增强

int a;
int a=10;//重定义

在c++中会报错。
(2)函数检测增强,参数类型和函数返回值

int getRectS(w,h){

}

在c++中不能跑,因为没有return,也没有说w,h是什么类型。
(3)函数调用检测增强,参数个数

void test2(){
	getRectS(10,10,10);
}

(4)类型转换检测增强,

char * p=(char *)malloc(sizeof(64)) //malloc返回值是void*

c++里要强转
(5)结构体增强

struct Person{
	int Age;
	void plusAge(){Age++;}; //c中结构体不可以加函数,但c++可
}

(6)c++可以不加入struct关键字

	struct Person p1;//c使用时必须加入struct关键字
	Person p2; //c++可以不加入struct关键字
	p2.Age=10;
	p2.plusAge();

(7)bool类型增强
c语言中没有bool类型

bool flag;//true or false

(8)三目运算符增强a>b?a:b
c语言返回”值“,c++返回”变量“。

int a=1;  
int b=20;  
printf("res=%d",a>b?a:b);//c语言写法
cout << (a>b?a:b) << endl;//c++写法
a>b?a:b=100;//c++写法,100赋值给b。c语言会失败

(9)const增强,一种只读数据,不能修改

c语言仍可以通过指针绕过而修改。伪常量
c++通过指针之后仍不会被修改。真正常量。

c语言中的const默认是外部链接;可以在其他文件访问。
c++中的const默认是内部链接,要使用extern提高作用域。

c语言中const分配内存问题?
c++中const分配内存问题?
在c++中,一个const不必创建内存空间,而在c中,一个const总是需要一块内存空间。
在c++中,是否为const常量分配内存空间依赖于如何使用。一般说来,如果一个const仅仅用来把一个名字用一个值代替(就像使用#define一样),那么该存储局空间就不必创建。
如果存储空间没有分配内存的话,在进行完数据类型检查后,为了代码更加有效,值也许会折叠到代码中。
不过,取一个const地址, 或者把它定义为extern,则会为该const创建内存空间。

1、const分配内存时,取地址会分配临时内存
2、extern编译器也会给const分配临时内存

void test01{  
    const int a=10;  
    int *p=(int*)&a;//会分配临时内存  
};

3、用普通变量初始化const的变量

void test02(){  
    int a=10;  
    const int b=a;//会分配内存  
    int *p=(int *)&b;  
    *p=1000;  
    cout<<b<<endl;  
}

4、自定义数据类型,用const初始化也会分配内存

struct Person{  
    string Name;  
    int Age;  
};  
void test03(){  
    const Person p1;  
//    p1.Name="aaa";  
    Person *p= (Person *)&p1;  
    p->Name="aaa";  
    (*p).Age=18;  
    cout<<p1.Name<<p1.Age<<endl;  
}

在c++中,出现在所有函数之外的const作用于整个文件(也就是说它在该文件外不可见),默认为内部连接,c++中其他的标识符一般默认为外部连接。

9、尽量以const 替换#define

#define MAX 1024
1、这max会在预处理阶段就被替换为1024,编译器看不到max。无非是想让max成为常量,用const也能实现。
2、define出来的变量没有作用域,从文件头到文件尾都有效(但可以指定生命周期)。如果要定义在指定作用域下有效的常量,需要用const。
3、define没有类型,不可进行类型检测。const有类型,可以进行编译器类型安全检查。

10、引用reference

引用是c++对c的扩充,引用可以直接理解为取别名.
&写早左侧,叫引用;写到右侧,叫取地址。
int &b=a:![[Pasted image 20220927092746.png]]
1、引用必须初始化

void test01(){  
    int &A; //会报错,必须初始化 
}

2、引用初始化后就不可以修改了

void test01(){  
    int a=10;  
    int &A=a;//引用初始化后就不可以修改了  
    int c=20;  
    b=c;//赋值失败。  
}

3、给数组起别名①

void test02(){  
    int arr[10];  
    for(int i=0;i<10;i++){  
        arr[i]=i;  
    }    
    //给数组起别名  
    int (&pArr)[10]=arr;  
    for(int i=0;i<10;i++){  
        cout<<pArr[i]<<" ";  
    }    cout<<endl;  
}

给数组起别名②

//一个具有10个元素的int类型的数组  
typedef int(ARRAYREF)[10];
ARRAYREF & pArr2=arr;

4、引用的注意事项
①引用必须引一块合法的内存空间
int &a=10错误,10没有空间
②不要返回局部变量的引用
③如果函数的返回值是引用,那么这个函数调用可以作为左值
5、引用的本质
在c++内部实现是一个指针常量
int &b=a,发现是引用,转换为int *b=&a
6、引用的使用场景
①指针的引用(待补充)
用一级的指针引用可以代替二级指针。
②常量的引用:
但最好不要这么写,临时变量找不到

void test(){  
    const int &ref=10;//加入const后,编译器处理:创建了临时变量tmp=10;再来const int &ref=tmp。会分配内存  
//    ref=10;//就不能修改了,会报错  
    //但能绕过编译器进行修改  
    int *p=(int *)&ref;  
    *p=1000;  
}

常量引用的使用场景,用来修饰形参为只读

void showValue(const int &val){  
    //如果只是想显示内容,不修改内容,那么就用const修饰这个形参  
    cout<<"val="<<val<<endl;  
}  
void test02(){  
    int a=10;  
    showValue(a);  
}

11、参数的三种传递方式

(1)值传递:不改变值。只是判断

void mySwap(int a,int b){  
    int tmp=a;  
    a=b;  
    b=tmp;  
    cout<<a<<" "<<b<<endl;  //20 10
}  
void test02(){  
    int a=10;  
    int b=20;  
    mySwap(a,b);  
    cout<<a<<" "<<b<<endl;  //10 20
} 

(2)地址传递:想改变值

void mySwap(int * a,int * b){  
    int tmp=*a;  
    *a=*b;  
    *b=tmp;  
    cout<<*a<<" "<<*b<<endl;  //20 10
}  
void test02(){  
    int a=10;  
    int b=20;  
    mySwap(&a,&b);  
    cout<<a<<" "<<b<<endl;  //20 10
}

(3)引用传递:类似于传地址

void mySwap(int & a,int & b){  //给a,b起别名
    int tmp=a;  
    a=b;  
    b=tmp;  
    cout<<a<<" "<<b<<endl;  
}  
void test02(){  
    int a=10;  
    int b=20;  
    mySwap(a,b);  
    cout<<a<<" "<<b<<endl;  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值