栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++基础知识(一)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++基础知识(一)

目录

1. 命名空间  ::

2. using 声明

3. 结构体加强

(1)不需要加struct就可以定义变量

(2)结构体内可以写函数

4. 不能进行隐式转换,必须是显式转换

5. 三目运算符

6. C/C++中的const

7. 引用(重难点)

(1)引用可以作为一个已定义变量的别名

(2)当定义函数时,按引用传递

(3)建立数组引用

(4)引用的本质

(5)指针引用

(6)常量引用

(7)引用的使用

① 引用作为函数的参数

② 引用作为函数的返回值

8. 内联函数

9. 函数的默认参数

10. 函数的占位参数

11. 函数传参的三种方式

12. 创建一个学生类


1. 命名空间  ::
namespace A{   //A 是空间的名字
    int a;
    void func()
    {}
}

(1)命名空间只能写在全局;

(2)可以嵌套;

namespace Aspace {  
    int a = 1;
    namespace B {
        int b;
    }
}

(3)命名空间是开放的,可以随时加入新成员;

(4)命名空间可以取别名;

namespace newSpace = oldSpace;
newSpace:新名字 
oldSpace:旧名字

(5)分文件编写代码时,如果.h中有两个命名空间,但是里边的成员函数或变量重名时,在.cpp中实现函数时需要加上命名空间。eg:

test.h:

#pragma once
#include 
using namespace std;

namespace Space1 
{
    void func();
}

namespace Space2
{
    void func();
}

test.c:

#include "test.h"
void Space1 :: func()  //需要在函数名之前加上命名空间的名字
{
    cout << "func" << endl;
}

(6)作用域运算符 ::

eg:

#include 
using namespace std;  //标准命名空间

namespace Aspace {   
    int aa = 1;
    void func()
    {
    }
    namespace B {
        int b = 3;
    }
}

namespace Cspace
{
    int c = 2 ;
}


int aa = 100;

int main()
{
    int aa = 10;
    cout << "aa =" << aa << endl;        //就近原则,打印局部变量aa的值
    cout << "::aa =" << ::aa << endl;    //如果::前边没有东西,则表示取全局的作用域,打印全局变量的aa
    cout << "Cspace::c =" << Cspace::c << endl;   //::前边加上命名空间的名字则打印命名空间中对应成员的值
    cout << "Aspace::B::b =" << Aspace::B::b << endl;

    system("pause");
    return EXIT_SUCCESS;
}

输出为:

aa =10
::aa =100
Cspace::c =2
Aspace::B::b =3

2. using 声明
#define _CRT_SECURE_NO_WARNINGS
#include 
using namespace std;

namespace A {
	int a = 1;
	int b = 2;
	int c = 3;
}

void test01()
{
	//using声明是让命名空间中某个标识符可以直接使用
	using A::a;
	cout << a << endl;

	int a = 50; //错误,因为using声明了某个变量,在该作用域内不能定义同名的变量
}

void test02()
{
	//using 编译指令,让某个命名空间中的标识符都可以直接使用
	using namespace A;
	cout << a << endl;

	int a = 10; //这里没错,因为这里类似于命名空间中的a为全局变量,而这个a是局部变量
}

3. 结构体加强

(1)不需要加struct就可以定义变量
struct Maker
{
	char name[64];
	int age;
};

void test()
{
    Maker a;
}

(2)结构体内可以写函数
struct Maker2
{
	int a;
	void func()
	{
		cout << "func" << endl;
	}
};

void test()
{
    Maker2 a2;
    a2.func();
}

4. 不能进行隐式转换,必须是显式转换
void test()
{
	char* p = (char*)malloc(64);
}

5. 三目运算符

(1)C语言中,三目运算符返回的是右值,不能被赋值;

void test()
{
	int a = 10;
	int b = 20;
    printf("%d",a > b ? a : b);
	//(a > b ? a : b) = 100;  //err
}

(2)C++中,三目运算符返回的是左值,是空间,可以被赋值;

void test()
{
	int a = 10;
	int b = 20;
	(a > b ? a : b) = 100;  
    cout<<"a ="<

输出为:

a=10;
b=100;

6. C/C++中的const
CC++
const修饰的变量会被存储在只读数据段,只要有定义即分配内存空间全局const当声明extern或者对变量取地址时,编译器才会分配存储地址,变量存储在只读数据段
局部const存储在堆栈区,不能直接改变变量的值,可以通过指针间接修改const的值

只有在分配了内存后,才能通过指针间接修改const变量的值。

① 对于const int a = 10这种,编译器会进行优化,将a替换为10,类似于#define;

② 如果用一个变量初始化const,比如const int a = b,那么也会给a分配内存;

③ 对于类对象,也会分配内存,如下代码所示。

默认为外部连接,当两个c文件中都有同样的const变量时,编译器会报重定义错误默认为内部连接,不会报重定义错误。如果想让C++中的const有外部链接,必须显式声明为:extern const int a = 10;
    const Person person; //未初始化age
	//person.age = 50; //不可修改
	Person* pPerson = (Person*)&person;
	//指针间接修改
	pPerson->age = 100;
	cout << "pPerson->age:" << pPerson->age << endl;

输出为:

pPerson->age:100

7. 引用(重难点)

(1)引用可以作为一个已定义变量的别名
void test02()
{
	int a = 10;
	int& b = a; //给a的空间取别名叫b
	b = 100;
	cout << a << endl;
}

输出为:100

而指针的写法是:

void test02()
{
	int a = 10;
	int* b = &a; 
	*b = 100;
}

(2)当定义函数时,按引用传递
void func(int &b)
{
    b = 100;
}

void test()
{
    int a = 10;
    func(a);
    cout << "a = " << a << endl;
}

输出为:a = 100

而C指针的写法是:

void func(int *b)
{
    *b = 100;
}

void test()
{
    int a = 10;
    func(&a);
    cout << "a = " << a << endl;
}

引用的注意:

  • ① & 在此不是求地址运算,而是起标识作用;
  • ② 引用创建时必须初始化;
  • ③ 引用一旦初始化后不能改变它的指向
  • ④ 必须引用一块合法的内存空间

(3)建立数组引用
int main()
{
	int arr[] = { 1,2,3 };
	//第一种方法
	typedef int(Arr)[3];  //定义数组类型
	Arr &arref = arr;     //建立引用

	//第二种方法,直接定义引用
	int(&arref2)[3] = arr;

	for (int i = 0; i < 3; i++)
	{
		cout << arref[i] << endl;
	}
}

(4)引用的本质

C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同。

int main()
{
	int a = 10;
	int& aRef = a; //自动转换为int* const aRef = &a;这也能说明引用为什么必须初始化
	aRef = 20; //内部发现aRef是引用,自动帮我们转换为: *aRef = 20;
}

 如下图所示:

(5)指针引用

在C语言中,如果想改变一个指针的指向,而不是它所指向的内容,则会使用二级指针,如下:

void func(char** tmp)
{
	char* p = (char*)malloc(64);
	memset(p, 0, 64);
	strcpy(p, "hello");
	*tmp = p;
}

void test()
{
	char* mp = NULL;
	func(&mp);
	cout << mp << endl;
}

改成引用的话:

void func(char* &tmp)
{
	char* p = (char*)malloc(64);
	memset(p, 0, 64);
	strcpy(p, "hello");
	tmp = p;
}

void test()
{
	char* mp = NULL;
	func(mp);
	cout << mp << endl;
}

(6)常量引用

定义格式:

const int& ref = val;
int main()
{
	//普通引用
	int a = 10;
	int& tmp = a;
	tmp = 20;

	//int &ref = 10;  err,不能给字面量取别名
	const int& tmp1 = 10;  //可以给const修饰的引用赋予字面量
	//编译器会把上边的代码变为:int x=10; const int &tmp1=x;
	//tmp2 = 20; err
}

(7)引用的使用

① 引用作为函数的参数
void func(int& a, int& b)
{
	int sum = a + b;
	cout << "sum = " << sum << endl;
}

void test()
{
	int a = 10;
	int b = 20;
	func(a, b);
}

② 引用作为函数的返回值

如果从函数中返回一个引用,必须像从函数中返回一个指针一样对待。当函数返回时,引用关联的内存一定要存在。

int& func()
{
	int b = 10;    //不能返回局部变量的引用
	int& p = b;
	return p;
}

int& func2()
{
	static int b = 10;
	return b;
}

void test()
{
	cout << "func=" << func() << endl;
	func() = 100;          //如果要函数当左值,那么该函数必须返回引用
	cout << "func2()=" << func2() << endl;
}

8. 内联函数

内联函数为了继承宏函数的效率,没有函数调用时的开销,又可以像普通函数那样,可以进行参数、返回值类型的安全检查,又可以作为成员函数。

内联函数也占用空间,但是相对于普通函数,只是省去了函数调用时的压栈、跳转、返回的开销,可以理解为内联函数是“以空间换时间”。

在普通函数前加上 inline 关键字使之成为内联函数。但是必须注意,函数体和声明结合在一起,否则编译器将它作为普通函数来对待。

inline void func(int a); //该写法没有任何效果

类内部的内联函数:

类内部定义内联函数时并不必须要加 inline,任何在类内部定义的函数自动成为内联函数。

c++内联编译会有一些限制:

  • 不能存在任何形式的循环语句;
  • 不能存在过多的条件判断语句;
  • 函数体不能过于庞大;
  • 不能对函数进行取址操作;

9. 函数的默认参数
int func(int a, int b = 0)  //b=0即为b的默认值
{
	return a + b;
}

注意:

  • 函数的默认参数从左向右,如果一个参数设置了默认参数,那么这个参数之后的参数都必须设置默认参数。
  • 函数声明和函数定义不能同时设置默认参数。

10. 函数的占位参数
void func(int a, int b, int)
{
	cout << "a+b = " << a + b << endl;
}

void func2(int a, int b, int=20)
{
	cout << "a+b = " << a + b << endl;
}

int main()
{
	func(10,20);     //err,占位参数也是参数,必须传参数
	func(10,20,30);  //ok
	func2(10,20);    //ok
	func2(10,20,30); //ok

	return EXIT_SUCCESS;
}

后边讲的操作符重载的后置++要用到这个。

11. 函数传参的三种方式

值传递、指针传递、引用传递

//值传递
void swap(int a, int b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
//指针传递
void swap2(int *a, int *b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
//引用传递
void swap3(int &a, int &b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

void myprint(int& a, int& b)
{
	cout << "a=" << a << "b=" << b << endl;
}

int main()
{
	int a = 10;
	int b = 20;
	swap(a,b);
	myprint(a, b);
	swap2(&a,&b);
	myprint(a, b);
	swap3(a,b);
	myprint(a,b);
}

上述三种交换结果,只有第一种值传递无法交换a,b的值。

12. 创建一个学生类
class Student
{
public:    //公有
	void setName(string Name)  //成员方法,也叫成员函数
	{
		name = Name;
	}
	void setID(int Id)
	{
		id = Id;
	}
	void myprint()
	{
		cout << "姓名:" << name << "n学号:" << id << endl;
	}
private:  //私有权限
	string name;  //成员属性
	int id;
};

int main()
{
	Student s;
	s.setName("Paul");
	s.setID(1);
	s.myprint();

	system("pause");
	return EXIT_SUCCESS;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1004571.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号