C++ 完全兼容C
一 创建一个简单的C++类项目
1 源文件和头文件分开:
- 右键项目-在文件资源管理器中打开文件夹
- 项目文件夹下创建两个文件夹(如:ConsoleApplication1\ConsoleApplication1 下 新建include、src文件夹)
- 头文件-添加现有项-选择include文件夹-创建一个.h文件,添加新的cpp文件到src目录
- 属性-C/C+± 常规- 附加包含目录-选择新建的.h文件夹(如include)-应用-确定
2 创建一个C++类
Teacher.h中声明
#pragma once
class MyTeacher
{
public:
MyTeacher(); //构造函数 (malloc)
~MyTeacher();//析构函数 释放在构造函数里面动态申请的内存 (free)
void setAge(int age);
int getAge();
void setName( char *name);
char* getName();
private:
int age;
char *name;
};
Teacher.cpp 引入头文件并实现
::代表限定符代表类的方法,如果不写,则是cpp中的方法
#pragma once
#include <Teacher.h>
#include <iostream>
//c++ 标准库的命名空间
using namespace std;
MyTeacher::MyTeacher() {
cout << " MyTeacher 构造函数 地址:" << this << endl;
}
MyTeacher::~MyTeacher() {
cout << " MyTeacher 析构函数 地址:" << this << endl;
}
// ::代表限定符
void MyTeacher::setAge(int age) {
this->age = age;
}
int MyTeacher::getAge() {
return this->age;
}
void MyTeacher::setName(char *name) {
cout << " MyTeacher setName" << name << endl;
this->name = name;
}
char* MyTeacher::getName() {
return this->name;
}
main.cpp使用
#include <Teacher.h>
#include <iostream>
using namespace std;
void fun() {
MyTeacher teacher;
teacher.setAge(18);
teacher.setName("张三");
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
}
void main() {
fun();
system("pause");
}
结果:
MyTeacher 构造函数 地址:00B3F9B0
teacher name: 张三
teacher age: 18
MyTeacher 析构函数 地址:00B3F9B0
3 命名空间
(类似于java package概念)
创建一个命名空间:
namespace NSP_A {
struct MyStudent
{
int age;
};
}
使用命名空间
NSP_A::MyStudent t;
t.age = 18;
使用标准库的命名空间
#include <iostream>
//使用using namespace std;之前
//std::cout << " MyTeacher 构造函数 地址:" << this << std::endl;
//使用之后
//c++ 标准库的命名空间
using namespace std;
cout << " MyTeacher 构造函数 地址:" << this << endl;
二 值传递和引用传递
定义一个方法,能够将Teacher的名称和年龄替换
1 值传递
//替换teacher java 肯定能够成功
//为什么这里只调用了析构函数,没有调用构造函数?
//值传递 存在值拷贝
void setFunc(MyTeacher teacher) {
teacher.setAge(31);
teacher.setName("yuehan");
cout << "setFunc teacher name: " << teacher.getName() << endl;
cout << "setFunc teacher age: " << teacher.getAge() << endl;
}
调用
void main() {
MyTeacher teacher;
teacher.setAge(18);
teacher.setName("张三");
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
setFunc(teacher);
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
system("pause");
}
输出结果:
MyTeacher 构造函数 地址:0115FED4
teacher name: 张三
teacher age: 18
setFunc teacher name: yuehan
setFunc teacher age: 31
MyTeacher 析构函数 地址:0115FDF8
teacher name: 张三
teacher age: 18
结果分析: Teacher的name和age没有被替换,setFunc只调用了析构函数没有调用构造函数
2 引用传递
//引用传递
//c++ 引用 是内存空间的别名 不存在拷贝 只传递内存别名
void setFuncY(MyTeacher &teacher) {
teacher.setAge(31);
teacher.setName("yuehan");
cout << "setFunc teacher name: " << teacher.getName() << endl;
cout << "setFunc teacher age: " << teacher.getAge() << endl;
}
调用:
void main() {
MyTeacher teacher;
teacher.setAge(18);
teacher.setName("张三");
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
setFuncY(teacher);
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
system("pause");
}
输出结果:
MyTeacher 构造函数 地址:00C2FD60
teacher name: 张三
teacher age: 18
setFunc teacher name: yuehan
setFunc teacher age: 31
teacher name: yuehan
teacher age: 31
最后发现替换成功
三 内存空间的分配
每页内存空间
-
.text段
可执行代码、只读变量,全局静态变量 -
.data段
已初始化且初值非0的全局变量和静态局部变量 -
.bss段
未初始化或初值为0的全局变量和静态局部变量 -
堆(heap)空间:
动态分配的内存(malloc 等api 分配在堆空间, c++中的new)
堆用于存放进程运行时动态分配的内存段,可动态扩张或缩减。堆中内容是匿名的,不能按名字直接访问,只能通过指针间接访问。 -
栈(stack)空间:
局部变量、函数参数、返回地址等(系统自动分配的临时内存)Linux有专门的寄存器管理栈内存(效率高)
四 引用
1 引用与引用别名
-
教课书上说的是引用是原变量的一个别名.
n 相当于m 的别名(绰号),对n 的任何操作就是对m 的操作。例如有个人叫是J,绰号是“马爸爸”。说“马爸爸”怎么怎么的,其实就是在说J。所以n 既不是m 的拷贝,也不是指向m 的指针,其实n就是m 它自己。
-
c++中的引用 (就是再堆中分配空间)
- 单纯给变量取别名没有任何意义,作为函数参数传递,能保证参数传递过程中不产生副本
- 引用可以直接操作变量,指针要通过取值(*p),间接操作变量,指针的可读性差
-
java的引用和句柄
内存分配在堆空间, 引用和句柄分配在栈空间 -
java中的引用(强引用,弱引用,软引用,虚引用)
2 指针和引用的区别
-
指针是一个实体,而引用仅是个别名;
-
引用使用时无需解引用(*),指针需要解引用;
-
引用只能在定义时被初始化一次,之后不可变;指针可变;
引用“从一而终”
-
引用没有 const,指针有 const,const 的指针不可变;
-
引用不能为空,指针可以为空;
-
“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
常用的引用方式(指针的引用—代替二级指针)