一、类的封装
访问权限:
公共权限public :类的内外都可以使用
私有权限private : 仅类内可以访问,继承后不可访问
保护权限protected :仅类内可以访问,继承后可以访问
#include <iostream> //标准输入输出控件
#include <iomanip>
#include <string> //使用string声明字符串时必须包含
#include <cstdlib> //汉化
using namespace std;
// 构造与析构
class Person
{
private:
string name;
int age;
public:
// 有参构造函数
Person(const string &name, int age)
{
this->name = name;
this->age = age;
};
// 析构函数
~Person() {}; // 对象销毁时清理内存
// 向外部提供访问内部属性的方法
void getMess()
{
cout << "构造函数初始化:" << name << age << endl;
};
protected:
};
int main()
{
system("chcp 65001 >nul"); // 汉化
// using std::cout;
Person p("zhangsan",25);//实例化一个叫张三,25岁的对象
cout << p.name << p.age <<endl;
return 0;
}
二、构造函数与析构函数
构造函数:
1.没有返回值也不需要写void
2.函数名称与类名相同
3.构造函数可以有参数,可发生重载
4.程序调用对象的时候会自动调用构造,无需手动调用,且只调用一次
析构函数:
1.没有返回值也不需要写void
2.函数名固定为 ~类名
3.析构函数不能有参数,也不能重载
4.程序运行结束会自动调用析构释放内存,无需手动调用,且只执行一次
(一)构造函数分类
1.按参数分类 有参数 无参数
2.按类型分类 普通构造 拷贝构造函数
拷贝构造函数:
Person( const Person &p ){
age = p.age;
}
(二)构造函数的调用方法
1.括号法
Person p;//无参构造,默认构造
Person p1(10);//有参构造
Person p2(p1);//拷贝构造
2.显示法
Person p = Person(10);
Person(10);//匿名对象,执行完后系统会立即回收匿名对象
Person p = Person(p1);//拷贝构造
注意:不要用拷贝构造函数创建初始化一个匿名对象 Person (p1) === Person p1
3.隐式法
Person p = 10; === Person p = Person(10);
Person p = P1;//拷贝构造
(三)拷贝构造函数的场景
1.使用一个创建完毕的对象来初始化一个新对象
#include <iostream> //标准输入输出控件
#include <iomanip>
#include <string> //使用string声明字符串时必须包含
#include <cstdlib> //汉化
using namespace std;
class Car
{
private:
int carNumber;
public:
// 构造函数的重构
// 默认构造函数,无参构造
Car() { cout << "调用无参构造函数" << endl; };
// 有参构造
Car(int num)
{
carNumber = num;
cout << "调用有参构造函数" << endl;
};
// 拷贝构造
Car(const Car &car)
{
carNumber = car.carNumber;
cout << "调用拷贝构造函数" << endl;
};
~Car() { cout << "调用析构函数" << endl; };
int getCarNumber()
{
return carNumber;
};
protected:
};
void test1()
{
Car car1;
Car car2(10);
Car car3(car2);
cout << "car2构造结果:" << car2.getCarNumber() << endl;
cout << "car3构造结果:" << car3.getCarNumber() << endl;
};
int main()
{
system("chcp 65001 >nul"); // 汉化
// using std::cout;
/* 拷贝构造函数的使用场景*/
test1(); // 使用一个创建完毕的对象来初始化一个新对象
return 0;
}
2.值传递的方式给函数参数传参
#include <iostream> //标准输入输出控件
#include <iomanip>
#include <string> //使用string声明字符串时必须包含
#include <cstdlib> //汉化
using namespace std;
class Car
{
private:
int carNumber;
public:
// 构造函数的重构
// 默认构造函数,无参构造
Car() { cout << "调用无参构造函数" << endl; };
// 有参构造
Car(int num)
{
carNumber = num;
cout << "调用有参构造函数" << endl;
};
// 拷贝构造
Car(const Car &car)
{
carNumber = car.carNumber;
cout << "调用拷贝构造函数" << endl;
};
~Car() { cout << "调用析构函数" << endl; };
int getCarNumber()
{
return carNumber;
};
protected:
};
void test2_1(Car c1) {
};
void test2()
{
Car c1;
test2_1(c1);
};
int main()
{
system("chcp 65001 >nul"); // 汉化
// using std::cout;
/* 拷贝构造函数的使用场景*/
test2(); // 值传递的方式给函数参数传参
return 0;
}
3.用值的方式返回一个局部对象
#include <iostream> //标准输入输出控件
#include <iomanip>
#include <string> //使用string声明字符串时必须包含
#include <cstdlib> //汉化
using namespace std;
class Car
{
private:
int carNumber;
public:
// 构造函数的重构
// 默认构造函数,无参构造
Car() { cout << "调用无参构造函数" << endl; };
// 有参构造
Car(int num)
{
carNumber = num;
cout << "调用有参构造函数" << endl;
};
// 拷贝构造
Car(const Car &car)
{
carNumber = car.carNumber;
cout << "调用拷贝构造函数" << endl;
};
~Car() { cout << "调用析构函数" << endl; };
int getCarNumber()
{
return carNumber;
};
protected:
};
Car test3_1()
{
Car c1;
return c1;
};
void test3()
{
Car c1 = test3_1();
/*
正常来说,这里会执行两次拷贝构造函数
第一次是返回时,return c1 会先将 c1 拷贝到一个临时对象(调用拷贝函数)
第二次是执行 Car c1 = 临时对象,会再将临时对象拷贝到 test3() 中的 c1(再调用一次拷贝构造函数)
但编译器会优化这两步复制,直接在 test3() 的 c1 内存位置构造 test3_1() 中的对象
在编译时关闭优化(如 GCC 用 -fno-elide-constructors 选项),就能看到拷贝构造函数被调用
*/
};
int main()
{
system("chcp 65001 >nul"); // 汉化
// using std::cout;
/* 拷贝构造函数的使用场景*/
test3(); // 用值的方式返回一个局部对象
return 0;
}
(四)构造函数的调用规则
1.默认情况下编译器至少给一个类提供三个默认构造函数(无参构造,析构函数,拷贝构造)
2.写了自定义的有参构造函数后,编译器不提供无参构造函数,但提供拷贝构造函数
3.写了自定义构造函数后,编译器不再提供其他构造函数
三、易混淆知识点
(一)class 与 struct 的区别
class的默认访问权限是private
struct的默认访问权限是public
(二)拷贝构造函数的参数可以不用const吗
非 const 引用只能绑定到 “可修改的左值”(如普通变量),无法绑定到常量对象或临时对象
class Car {
public:
int id;
// 拷贝构造函数:参数为非 const 引用
Car(Car& other) {
this->id = other.id;
}
};
int main() {
Car c1;
Car c2 = c1; // 正确:c1 是可修改的左值,可绑定到非 const 引用
const Car c3; // 常量对象
Car c4 = c3; // 错误:无法用非 const 引用绑定常量对象
Car c5 = Car(); // 错误:无法用非 const 引用绑定临时对象(Car() 是临时对象)
return 0;
}
1539

被折叠的 条评论
为什么被折叠?



