C++核心编程(四)类和对象
(一). 对象的初始化和清理:*(构造函数和析构函输数)
(1)构造函数:
//******————《构造函数》————******//
#include <iostream>
using namespace std;
#include<string>
class Person
{
public:
Person() //构造函数调用且只调用一次,前面不需要加void什么的
{
cout << "构造函数的调用:" << endl;
}
};
void test01()
{
Person p;
}
int main()
{
Person p; 或者 test01();都可
//编译器自动调用构造函数,无需传参呀什么的,没有调用普通函数麻烦
system("pause");
return 0;
}
(2).析构函数:
但是主函数执行完后也会释放,释放时机就在system后,看不见。(如下图)
*(二)。构造函数的分类和调用:
(1).括号调用法,代码已包含分类,仔细看。
//******————《构造函数分类以及调用》————******//
#include <iostream>
using namespace std;
#include<string>
//按照分类,分为无参构造和有参构造
class Person
{
public:
//构造函数
Person() //无参(默认构造)
{
cout << "Person构造函数的调用:" << endl;
}
Person(int a) //有参
{
age = a;
cout << "Person ‘有参’ 构造函数的调用:" << endl;
}
//拷贝构造函数 ( 拷贝出一份一模一样的数据)
Person(const Person &p) //由于是拷贝,传进来的不可修改,要加const
{
age = p.age; //直接拷贝
cout << "Person '拷贝函数调用'" << endl;
}
~Person()
{
cout << "Person析构函数的调用:" << endl;
}
int age;
};
void test01()
{
//1 括号法
Person p; //无参调用,不能Person p(); 这样调用会被当成函数声明
Person p1(20); //有参调用
Person p2(p1); //拷贝参数的调用 ,如果拷贝对象用错了,变成比如p3,年龄就是乱码,因为没有p3的1拷贝对象
cout << "p1的年龄为: "<< p1.age << endl;
cout << "p2的年龄为: "<< p2.age << endl;
//2 显示法
//3 隐式传递法
}
int main()
{
test01();
system("pause");
return 0;
}
(2).显示法: 其余代码类似上面。 理解: Person(10);叫匿名对象,将他赋给p1,就相当于在给他起名。
注意:
(3).隐式传递法:(自己输的时候吧年龄改成了30)
(三) 拷贝构造函数的调用方式:
//******————《拷贝构造函数的调用时机》————******//
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "默认 ,构造函数的调用!!!" << endl;
}
Person(int age)
{
cout << "默认 ,构造函数的调用!!!" << endl;
Age = age;
}
Person(const Person &p)
{
cout << "拷贝 ,构造函数的调用!!!" << endl;
Age = p.Age;
}
~Person()
{
cout << "析构 ,构造函数的调用!!!" << endl;
}
int Age;
};
********** 1.使用一个已经创建完毕的对象来初始化一个对象
//void test01()
//{
// Person p1(20);
// Person p2(p1); //拷贝p1
// cout << "p1的年龄为:" << p1.Age << endl;
// cout << "p2的年龄为:" << p2.Age << endl;
//}
//******* 2.值传递的方式
//void doWork(Person p2)
//{
// cout << "p2的年龄为:" << p2.Age <<endl;
//
//}
//
//void test02()
//{
// Person p1=Person(20);
// doWork(p1);
// cout << "p1的年龄为:" << p1.Age << endl;
//}
//******3.值方式返回局部对象 (这种方式理解较难,好好看结果黄字)
Person doWork2()
{
Person p1=Person(20);
cout << "p1的年龄为:" << p1.Age << endl;
return p1;
}
void test03()
{
Person p2 = doWork2();
cout << "p2的年龄为:" << p2.Age << endl;
}
int main()
{
//test01(); //第一种方法
//test02(); //第二种方法
test03(); //第三种方法
system("pause");
return 0;
}
(1)第一种方式的结果(过程看程序注释):
(2)第二种方式的结果(过程看程序注释):
(3)第三种调用结果(过程看程序注释):
(四)构造函数的调用规则:
(1).此时有拷贝构造函数:Person(const Person &p) {}
结果如下:
//******————《构造函数的调用规则》————******//
#include <iostream>
using namespace std;
class Person
{
public:
int Age;
Person()
{
cout << "默认构造!!!" << endl;
}
Person(int age)
{
cout << "有参构造函数!!!" << endl;
Age = age;
}
Person(const Person& p)
{
cout << "Person的拷贝函数的调用!!!" << endl;
Age = p.Age;
}
~Person()
{
cout << "析构函数!!!" << endl;
}
};
void test01()
{
Person p1; //创建个体p1
p1.Age = 18;
Person p2(p1);
cout << "p2的年龄为: "<< p2.Age <<endl;
}
int main()
{
test01();
system("pause");
return 0;
}
(2).现在删去拷贝构造函数:(此时编译器会自动帮你默默写一个拷贝构造)
结果如图:
(3).再将默认构造函数删去:
由于:我们写了有参构造函数,编译器便不会在提供默认构造函数,但依然会提供拷贝构造函数。(如下图:)
此时报错:
但是不影响有参调用:
(4).如果写了拷贝构造函数,编译器便不提供其他构造,想要只能手写:
此时只有拷贝构造可以调,默认和有参编译器不会给你写了。