1、程序的内存模型
①代码区:存放函数体的二进制代码,由操作系统进行管理
②全局区:存放全局变量和静态变量以及常量
③栈区:由编译器自动分配和释放,存放函数的参数值、局部变量等。
④堆区:由程序员分配和释放,若程序员不释放,程序结束时有操作系统回收。
①代码区:在运行程序之前就已经存在。特点是共享和只读。 ②全局区:在运行程序之前就已经存在。
#include "iostream"
#include "string"
using namespace std;
int g_a;
const int c_g_a = 10;
const string c_str = "hello";
int main()
{
int l_a;
const int c_l_a = 10;
const string c_l_str = "hello";
static int s_l_a;
cout << "全局变量地址为:" << (int)&g_a << endl;
cout << "全局常量地址为:" << (int)&c_g_a << endl;
cout << "全局字符常量地址为:" << (int)&c_str << endl;
cout << "静态变量地址为:" << (int)&s_l_a << endl;
cout << "局部变量地址为:" << (int)&l_a << endl;
cout << "局部常量地址为:" << (int)&c_l_a << endl;
system("pause");
return 0;
}
③栈区 注意不要放回局部变量的地址。
#include "iostream"
#include "string"
using namespace std;
int * aa(void)
{
int a = 10;
return &a;
}
int main()
{
int *p = aa();
cout << *p << endl;
cout << *p << endl;
system("pause");
return 0;
}
④堆区
#include "iostream"
#include "string"
using namespace std;
int * aa(void)
{
int *a = new int(10);
return a;
}
int main()
{
int *p = aa();
cout << *p << endl;
cout << *p << endl;
system("pause");
return 0;
}
2、堆栈开辟变量和数组以及空间的释放
#include "iostream"
#include "string"
using namespace std;
int main()
{
int *p = new int(10);
cout << *p << endl;
int *arr = new int[10];
for (int i = 0; i < 10; i++)
{
arr[i] = i;
}
for (int i = 0; i < 10; i++)
{
cout << arr[i] << " ";
}
cout << endl;
delete p;
delete[] arr;
system("pause");
return 0;
}
3、引用 引用必须初始化,而且初始化后不能再更改,即不能改变指向。
#include "iostream"
#include "string"
using namespace std;
int main()
{
int a = 10;
int &b = a;
cout << "a= " << a << endl;
cout << "b= " << b << endl;
b = 20;
cout << "a= " << a << endl;
cout << "b= " << b << endl;
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
void swap(int &a, int &b);
int main()
{
int a = 10;
int b = 20;
cout << "交换前:" << endl;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
swap(a, b);
cout << "交换后:" << endl;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}
void swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
#include "iostream"
#include "string"
using namespace std;
int& test1(void);
int& test2(void);
int main()
{
int &b = test1();
cout << "b= "<< b << endl;
cout << "b= "<< b << endl;
int &c = test2();
cout << "c= " << c << endl;
cout << "c= " << c << endl;
system("pause");
return 0;
}
int& test1(void)
{
int a = 10;
return a;
}
int& test2(void)
{
static int a = 10;
return a;
}
引用其实就是指针常量
int &a = b等价于int * const a = &b;
#include "iostream"
#include "string"
using namespace std;
int main()
{
int &a = 10;
const int &a = 10;
system("pause");
return 0;
}
常量引用经常用于函数的形参,即防止误操作对数据造成损坏。
eg:
void datashow(const int & a)
{
cout<<a<<endl;
}
4、函数默认参数
#include "iostream"
#include "string"
using namespace std;
int add1(int a, int b=10, int c=20);
int main()
{
cout << add1(10) << endl;
system("pause");
return 0;
}
int add1(int a, int b, int c)
{
return a + b + c;
}
5、占位参数
#include "iostream"
#include "string"
using namespace std;
int add1(int a, int b = 10, int = 10);
int main()
{
cout << add1(10) << endl;
system("pause");
return 0;
}
int add1(int a, int b, int)
{
return a + b;
}
6、函数重载
函数重载的条件:
①两个函数的作用域相同
②两个函数的函数名相同
③两个函数的形参类型不同或者个数不同或者顺序不同
#include "iostream"
#include "string"
using namespace std;
void function()
{
cout << "function1()" << endl;
}
void function(int a)
{
cout << "function1(int a)" << endl;
}
void function(int a, int b)
{
cout << "function1(int a, int b)" << endl;
}
void function(int a, double b)
{
cout << "function1(int a, double b)" << endl;
}
void function(double a, int b)
{
cout << "function1(double a, int b)" << endl;
}
int main()
{
function();
function(1);
function(1, 1);
function(1, 0.1);
function(0.1, 1);
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
void function(int &a)
{
cout << "function1(int a)" << endl;
}
void function(const int &a)
{
cout << "function1(const int &a)" << endl;
}
int main()
{
int a = 10;
function(10);
function(a);
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
void function(const int &a)
{
cout << "function1(const int &a)" << endl;
}
void function(int a, int b=10)
{
cout << "function1(int a, int b)" << endl;
}
int main()
{
function(1);
system("pause");
return 0;
}
7、类
#include "iostream"
#include "string"
using namespace std;
#define PI 3.14
class Circle
{
public:
double r;
double cacluate_c(double a)
{
return 2 * PI*r;
}
};
int main()
{
Circle a;
cout << "请输入圆的半径:";
cin >> a.r;
cout << "圆的周长为:" << a.cacluate_c(a.r) << endl;
system("pause");
return 0;
}
类中的属性也叫做成员属性、成员变量
类中的行为也叫做成员函数、成员方法
8、访问权限
①公共权限:public,类内可以访问,类外也可以访问
②保护权限:protected,类内可以访问,类外不可以访问,子类可以访问
③隐私权限:private,类内可以访问,类外不可以访问,子类不可以访问
#include "iostream"
#include "string"
using namespace std;
#define PI 3.14
class Person
{
public:
string name="张三";
protected:
string car="拖拉机";
private:
long card = 12345;
};
int main()
{
Person p;
p.name = "李四";
p.car = "奔驰";
p.card = 12346;
system("pause");
return 0;
}
struct:默认权限是public
class:默认权限是private
#include "iostream"
#include "string"
using namespace std;
#define PI 3.14
class Person
{
public:
void set_name(string a)
{
name = a;
cout << "名字修改完毕!" << endl;
}
void get_name()
{
cout << "名字为:" << name << endl;
}
void get_car()
{
cout << "车为:" << car << endl;
}
void set_card(long a)
{
card = a;
cout << "银行卡密码修改完毕!" << endl;
}
private:
string name = "张三";
string car = "拖拉机";
long card = 12345;
};
int main()
{
Person p;
p.get_name();
p.set_name("李四");
p.get_car();
p.set_card(123);
system("pause");
return 0;
}
9、构造函数与析构函数
构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数有编译器自动调用,无需手动调用。
析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。
#include "iostream"
#include "string"
using namespace std;
#define PI 3.14
class Person
{
public:
Person()
{
cout << "已调用构造函数" << endl;
}
~Person()
{
cout << "已调用析构函数" << endl;
}
};
void test1()
{
Person p1;
}
int main()
{
cout << "在main函数中实例化对象" << endl;
Person p2;
cout << "在子函数中实例化对象" << endl;
test1();
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
#define PI 3.14
class Person
{
public:
Person()
{
cout << "已调用无参构造函数" << endl;
}
Person(int a)
{
cout << "已调用有参构造函数" << endl;
}
Person(const Person &a)
{
cout << "已调用拷贝构造函数" << endl;
age = a.age;
}
~Person()
{
cout << "已调用析构函数" << endl;
}
int age;
};
void test1()
{
Person p1;
}
int main()
{
Person p1;
Person p2(10);
p2.age = 10;
Person p3(p2);
cout << "p3的age=" << p3.age << endl;
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
#define PI 3.14
class Person
{
public:
Person()
{
cout << "已调用无参构造函数" << endl;
}
Person(int a)
{
cout << "已调用有参构造函数" << endl;
}
Person(const Person &a)
{
cout << "已调用拷贝构造函数" << endl;
age = a.age;
}
~Person()
{
cout << "已调用析构函数" << endl;
}
int age;
};
void test1()
{
Person p1;
}
int main()
{
Person p1;
Person p2(10);
Person p3(p2);
Person p4 = Person();
Person p5 = Person(10);
Person p6 = Person(p5);
Person p7 = 10;
Person p8 = p7;
Person(10);
system("pause");
return 0;
}
拷贝构造函数的使用的三种场景:
①使用一个已经创建完毕的对象来初始化一个新对象。
②值传递的方式给函数形参传值。
③以值方式返回局部对象。
默认情况下:C++编译器至少给一个类添加三个函数:
1、默认构造函数(无参,函数体为空)
2、默认析构函数(无参,函数体为空)
3、默认拷贝构造函数,对属性进行拷贝。
特点:①如果用户定义了有参构造函数,则C++不再提供默认无参构造,但会提供默认拷贝
②如果用户定义拷贝函数,C++不会再提供其他构造 函数。
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作。
#include "iostream"
#include "string"
using namespace std;
class Person
{
public:
Person()
{
cout << "已调用无参构造函数" << endl;
}
Person(int a)
{
age = a;
cout << "已调用有参构造函数" << endl;
}
~Person()
{
cout << "已调用析构函数" << endl;
}
int age;
};
void test1()
{
Person p1(16);
cout << "p1的年龄=" << p1.age << endl;
Person p2(p1);
cout << "p2的年龄=" << p2.age << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
class Person
{
public:
Person()
{
cout << "已调用无参构造函数" << endl;
}
Person(int a,int b)
{
age = a;
Height = new int(b);
cout << "已调用有参构造函数" << endl;
}
~Person()
{
if (Height != NULL)
{
delete Height;
Height = NULL;
}
cout << "已调用析构函数" << endl;
}
int age;
int *Height;
};
void test1()
{
Person p1(16,180);
cout << "p1的年龄=" << p1.age << endl;
Person p2(p1);
cout << "p2的年龄=" << p2.age << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
运行上面这个程序会引发异常,这是因为在 p1和p2都执行析构函数,所以将Height的地址释放了两次,本来只需要释放一次就行了。解决这个问题的方法就是自己写拷贝构造函数,对于在堆区定义的成员属性,在拷贝构造函数中再new一个空间。
#include "iostream"
#include "string"
using namespace std;
class Person
{
public:
Person()
{
cout << "已调用无参构造函数" << endl;
}
Person(int a,int b)
{
age = a;
Height = new int(b);
cout << "已调用有参构造函数" << endl;
}
Person(const Person& p)
{
age = p.age;
Height = new int(*p.Height);
}
~Person()
{
if (Height != NULL)
{
delete Height;
Height = NULL;
}
cout << "已调用析构函数" << endl;
}
int age;
int *Height;
};
void test1()
{
Person p1(16,180);
cout << "p1的年龄=" << p1.age << endl;
Person p2(p1);
cout << "p2的年龄=" << p2.age << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
class Phone
{
public:
Phone()
{
cout << "已调用Phone默认构造函数" << endl;
}
Phone(string a)
{
phone_name = a;
cout << "已调用Phone有参构造函数" << endl;
}
~Phone()
{
cout << "已调用Phone析构函数" << endl;
}
string phone_name;
};
class Person
{
public:
Person()
{
cout << "已调用Person无参构造函数" << endl;
}
Person(int a,string b)
{
age = a;
phone.phone_name = b;
cout << "已调用Person有参构造函数" << endl;
}
~Person()
{
cout << "已调用Person析构函数" << endl;
}
int age;
Phone phone;
};
void test1()
{
Person p(10,"华为");
}
int main()
{
test1();
system("pause");
return 0;
}
10、静态成员变量与函数
#include "iostream"
#include "string"
using namespace std;
class Person
{
public:
static void func_1()
{
cout << "static void func_1()" << endl;
a = 20;
}
static int a;
};
int Person::a = 10;
void test1()
{
Person p1;
Person p2;
p1.func_1();
cout << "p1.a=" << p1.a << endl;
cout << "p2.a=" << p2.a << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
class Person1
{
};
class Person2
{
public:
int a;
};
class Person3
{
public:
int a;
static int b;
void function1()
{
}
static void function2()
{
}
};
int Person3::b = 10;
void test1()
{
Person1 p1;
Person2 p2;
Person3 p3;
cout << "sizeof(p1)=" << sizeof(p1) << endl;
cout << "sizeof(p2)=" << sizeof(p2) << endl;
cout << "sizeof(p3)=" << sizeof(p3) << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
11、this指针
this指针的用途:
①当形参和成员变量名相同时,可以用this指针来区分
②在类的非静态成员函数中返回对象本身,可以用return *this
#include "iostream"
#include "string"
using namespace std;
class Person1
{
public:
void fun(int age)
{
age = age;
}
int age;
};
class Person2
{
public:
void fun(int age)
{
this->age = age;
}
int age;
};
void test1()
{
Person1 p1;
Person2 p2;
p1.fun(10);
p2.fun(10);
cout << "p1.age=" << p1.age << endl;
cout << "p2.age" << p2.age << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
class Person
{
public:
Person& fun(Person p)
{
age += p.age;
return *this;
}
int age=10;
};
void test1()
{
Person p1;
Person p2;
p2.fun(p1).fun(p1);
cout << "p1.age=" << p1.age << endl;
cout << "p2.age=" << p2.age << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
12、常函数
常函数:用const修饰,常函数内不可以修改成员属性,但是mutable修饰的成员变量可以修改
常对象:用const修饰,常对象只能调用常函数。
#include "iostream"
#include "string"
using namespace std;
class Person
{
public:
void fun() const
{
b = 20;
}
void fun_2()
{
}
int age;
mutable int b;
};
void test1()
{
Person p1;
const Person p2;
p2.fun();
}
int main()
{
test1();
system("pause");
return 0;
}
13、友元
#include "iostream"
#include "string"
using namespace std;
class Person
{
friend void test1();
public:
int get_age()
{
return age;
}
private:
int age = 10;
};
void test1()
{
Person p;
cout << p.age << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
class Buliding
{
friend class Goodgay;
public:
Buliding();
string sittingroom;
private:
string bedroom;
};
Buliding::Buliding()
{
sittingroom = "客厅";
bedroom = "卧室";
}
class Goodgay
{
public:
Goodgay();
void visit();
Buliding *home;
};
Goodgay::Goodgay()
{
home = new Buliding;
}
void Goodgay::visit()
{
cout << "好基友正在访问:" << home->sittingroom << endl;
cout << "好基友正在访问:" << home->bedroom << endl;
}
void test1()
{
Goodgay gg;
gg.visit();
}
int main()
{
test1();
system("pause");
return 0;
}
#include "iostream"
#include "string"
using namespace std;
class Buliding;
class Goodgay
{
public:
Goodgay();
void visit1();
void visit2();
Buliding *home;
};
class Buliding
{
friend void Goodgay::visit1();
public:
Buliding();
string sittingroom;
private:
string bedroom;
};
Buliding::Buliding()
{
sittingroom = "客厅";
bedroom = "卧室";
}
Goodgay::Goodgay()
{
home = new Buliding;
}
void Goodgay::visit1()
{
cout << "好基友1正在访问:" << home->sittingroom << endl;
cout << "好基友1正在访问:" << home->bedroom << endl;
}
void Goodgay::visit2()
{
cout << "好基友2正在访问:" << home->sittingroom << endl;
}
void test1()
{
Goodgay gg;
gg.visit1();
gg.visit2();
}
int main()
{
test1();
system("pause");
return 0;
}
14、运算符重载
#include "iostream"
#include "string"
using namespace std;
class Person
{
public:
int a=10;
int b=10;
Person operator + (Person &p)
{
Person temp;
temp.a = this->a + p.a;
temp.b = this->b + p.b;
return temp;
}
};
void test1()
{
Person p1;
Person p2;
Person p3;
p3 = p1 + p2;
cout << "p3.a=" << p3.a << endl;
cout << "p3.b=" << p3.b << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
|