1. 访问权限
- public :公共权限
- protected:保护权限,子类可以访问
- private:私有权限,仅仅自己可以访问
2. struct 和class区别
- 在C++中,struct和class唯一的区别在于默认的访问权限不同
- struct默认权限为公共
- class默认权限为私有
3. 属性成员私有化
- 优点1:将所有成员属性设置为私有,可以自己控制读写权限
- 优点2:对于写权限,我们可以检测数据的有效性
class Person
{
public:
void setName(string name)
{
_name = name;
}
string getName()
{
return _name;
}
int getAge()
{
return _age;
}
void setLover(string lover)
{
_lover = lover;
}
private:
string _name; // 可读 可写
int _age; // 可读
string _lover; // 可写
};
4. 把.hpp(或称为.h)文件和.cpp文件抽出来
创建Person类
#ifndef hanshu_hpp
#define hanshu_hpp
#pragma once
using namespace std;
#include <stdio.h>
#include <iostream>
class Person
{
public:
void setName(string name);
string getName();
int getAge();
void setLover(string lover);
private:
string _name; // 可读 可写
int _age; // 可读
string _lover; // 可写
};
#endif /* hanshu_hpp */
#include "hanshu.hpp"
#include <iostream>
using namespace std;
void Person::setName(string name)
{
_name = name;
}
string Person::getName()
{
return _name;
}
int Person::getAge()
{
return _age;
}
void Person::setLover(string lover)
{
_lover = lover;
}
5. 对象的初始化和清理
class Cat
{
public:
//一、构造函数
/**
1. 没有返回值, 不用写void
2. 函数名 与类名相同
3. 构造函数可以有参数,可以发生重载
4.创建对象的时候,构造函数会被自动调用,而且只调用一次
*/
Cat()
{
cout << "cat 构造函数调用" << endl;
}
//二、析构函数
/**
1. 没有返回值 不写void
2.函数名和类名相同 在名称前加~
3.析构函数不可以有参数,不可以发生重载
4.对象在销毁前,会被自动调用,而且只调用一次
*/
~Cat()
{
cout << "cat 析构函数调用" << endl;
}
};
6. 有参、无参、拷贝 – 构造函数
class Pig
{
public:
Pig()
{
cout << "pig 无参构造函数" << endl;
}
Pig(int a)
{
_age = a;
cout << "pig 有参构造函数" << endl;
}
Pig(const Pig &p)
{
_age = p._age;
cout << "pig 拷贝构造函数" << endl;
}
~Pig()
{
cout << "pig 析构函数" << endl;
}
int _age;
};
int main(int argc, const char * argv[]) {
// 一、括号法
// Pig p;
// Pig p2(10);
// Pig p3(p);
// Pig p(); // 不要这样写
// 注意事项1:
// 1. 调用默认构造函数时候,不要加(),因为编译器会误认为是一个函数的声明
// 二、显示法
Pig p1;
Pig p2 = Pig(10);
Pig p3 = Pig(p2);
Pig(10); // 匿名对象 特点:当前行执行结束后,系统会立即回收匿名对象
// 注意事项2:
// 2. 不要利用拷贝构造函数 初始化匿名对象
// Pig(p2); // 报错:Redefinition of 'p2' 因为 Pig(p2) 会被编译器转换为 Pig p2; 重复定义了对象
// 三、隐式转换法
Pig p4 = 10; // 会被转换为 Pig p4 = Pig(10);
Pig p5 = p4; // 拷贝构造
return 0;
}
7. 拷贝构造函数调用时机
- C++ 中拷贝构造函数调用时机通常有三种情况
-
- 使用一个已经创建完毕的对象来初始化一个新对象
-
- 值传递的方式给函数参数传值
-
- 以值方式返回局部对象
int main(int argc, const char * argv[]) {
// 1. 使用一个已经创建完毕的对象来初始化一个新对象
// Pig p1 = Pig(10);
// Pig p2 = p1;
/** 打印内容
pig 无参构造函数
pig 拷贝构造函数
pig 析构函数
pig 析构函数
*/
//2. 值传递的方式给函数参数传值
// Pig p3;
// eat(p3); // 值传递,内部会拷贝一份对象,所以会调用拷贝构造函数
/** 打印内容
pig 无参构造函数
pig 拷贝构造函数
pig 析构函数
pig 析构函数
*/
// 3. 以值方式返回局部对象
Pig p = getPig();
cout << "函数调用的地址:" << (int*)&p << endl;
/** 打印内容(在Mac平台下,用xcode打印如下,但是原来教学视频在Windows下,打印的地址却不一样,会调用拷贝构造函数,所以严格意义来说,这个应该和平台有关系)
pig 无参构造函数
函数创建的地址:0x7ff7bfeff2d8
函数调用的地址:0x7ff7bfeff2d8
pig 析构函数
*/
return 0;
}
8. 构造函数调用规则
一、 默认情况下,C++编译器至少给一个类添加3个函数
-
- 默认构造函数(无参,函数体为空)
-
- 默认析构函数(无参,函数体为空)
-
- 默认拷贝构造函数,对属性进行值拷贝
二、构造函数调用规则如下:
-
- 如果用户定义有参构造函数,C++不再提供默认无参构造,但是会提供默认拷贝构造
-
- 如果用户定义拷贝构造函数,C++不会再提供其他构造函数
9.深拷贝和浅拷贝
概念:
- 深拷贝:重新开辟一块内存,指向新的地址
- 浅拷贝:新的指针,指向原来的内存地址
class Horse
{
public:
Horse()
{
cout << "Horse 无参构造函数" << endl;
}
Horse(int age, int height)
{
_age = age;
_height = new int(height);
cout << "Horse 有参构造函数" << endl;
}
Horse(Horse &h)
{
_age = h._age;
_height = new int(*h._height); // 通过new,开辟一块新的内存空间,深拷贝
// _height = h._height; // 指针的值引用,浅拷贝
cout << "Horse 拷贝构造函数" << endl;
}
~Horse()
{
delete _height; // 浅拷贝的时候,第二个对象是否这个指针引用的值的时候,会释放失败,崩溃,深拷贝则不会
_height = NULL;
cout << "Horse 析构函数" << endl;
}
int _age;
int *_height;
};
int main(int argc, const char * argv[]) {
Horse h1(3,5);
Horse h2(h1);
cout << "h1的年龄:" << h1._age << ", h1的身高:" << *h1._height << endl;
cout << "h2的年龄:" << h2._age << ", h2的身高:" << *h2._height << endl;
return 0;
}
10. 初始化列表方式
class Fish
{
public:
// 1.传统初始化方式
// Fish(int a, int b, int c)
// {
// _a = a;
// _b = b;
// _c = c;
// }
// 2. 初始化列表方式初始化
Fish(int a, int b, int c) : _a(a), _b(b), _c(c)
{
// do else things...
}
private:
int _a;
int _b;
int _c;
};
11. 静态成员
- 静态成员就是在成员变量和成员函数前加上static关键字,称为静态成员
- 分类
- 静态成员变量
- 所有对象共享同一份数据
- 在编译阶段分配内存
- 类内声明,类外初始化
- 静态成语函数
- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量
class Bird
{
public:
static int _age;
static void test()
{
_height = 30;
// _length = 1; // 无法访问非静态成员变量,会报错
cout << "static void test 调用" << endl;
}
private:
static int _height;
int _length;
static void test2()
{
cout << "类外无法访问私有静态成员函数" << endl;
}
};
int Bird::_age = 10; // 类内声明,类外初始化
int main(int argc, const char * argv[]) {
Bird b1;
cout << "b1的age: " << b1._age << endl;
Bird b2;
b2._age = 20;
cout << "b1的age: " << b1._age << endl;
// 通过类访问静态成员变量
cout << "通过类访问静态成员变量: " << Bird::_age << endl;
// cout << "通过类访问静态成员变量: " << Bird::_height << endl; // 访问不了私有静态成员变量
// 静态成员函数访问的两种方式
b1.test(); // 1. 通过对象访问
Bird::test(); // 2. 通过类访问
return 0;
}
|