C++类与对象之构造函数
C++类的基本格式
首先是C++类的一个基本格式
class 基类名
{
public://成员类可以访问 ,类外也可以访问。
默认构造函数命名:类名(){} //初始化函数,可以重载,不需要返回数据类型。
有参构造函数命名:类名(){参数} //初始化函数,可以重载,不需要返回数据类型。
拷贝构造函数命名:类名(基类 &类名) //将传入的人身上的所有属性,拷贝到我身上。
析构函数命名:~类名(){} //结尾进行清洗,不能重载。
//属性。
//方法(行为)。
private: //类内可以访问,类外不可以访问。
protected://类内可以访问,派生类可以访问,类外不能访问。
};
struct 和 class 区别
struct默认权限是公共
class默认权限是私有
C++类构造函数的调用方法
-
括号法:
#include<iostream> #include<string> using namespace std; class Person { public: Person(); Person(string &name); //Person(const Person &obj); ~Person(); public: string name="1"; }; Person::Person(){ cout << "Person无参构造" << endl; } Person::Person(string &name){ this->name = name; cout << "Person有参构造" << endl; } /* Person::Person(const Person &obj){ cout << "Person拷贝构造" << endl; }*/ Person::~Person(){} int main(){ Person P1; string name = "卡卡罗特"; Person P2(name); Person P3(P2); //如果采用默认的拷贝构造,则输出name时,会输出卡卡罗特 cout << P3.name << endl; return 0; }
当然你也可以通过
Person(const Person &obj)
重写拷贝构造函数 -
显示法
Person P4 = Person(name); cout << P4.name << endl; Person P5 = Person(P3); cout << P5.name << endl;
可以把这里的类(参数)单独拿出来属于匿名对象
使用时机:例如你用vector容器管理一个类的数组时,你可以不需要定义名字,直接使用匿名对象,然后push_back(Person())
-
隐式转换法
- 类 命名 = 参数; //有参构造
- 类 命名 = 命名对象; //拷贝构造,构造之后在赋值
Person P6 = name; //注意这里的name必须是string,才能触发隐式转换 Person P7 = P3; cout << P7.name << endl;
int a = 10;
int a;
a = 10
上述两者是不一样的。
构造函数调用规则
可以运行我上面的案例,注释掉一部分代码,进行测试
如果我们在合作编写代码时,不希望对方使用拷贝构造,有两种方法
方法一
可以将其设置在private下面
方法二
C++11的新特性中可以设置Person(const Person &obj) = delete;
拷贝构造函数的使用时机
上面讲了那么多,无论是默认构造函数还是有参构造亦或者隐式转换赋值都有他们被使用的地方,那么对于拷贝构造函数,又常常在什么情况下使用呢,这里我具几个简单的例子来说明。
C++中拷贝构造函数的调用时机有三种:
1 使用一个已经创建完毕的对象来初始化一个新对象
2 值传递的方式给函数参数传值
3 以值方式返回局部对象
class Person
{
public:
Person()
{
cout << "Person默认构造函数调用" << endl;
}
Person(int age)
{
cout << "Person有参构造函数调用" << endl;
m_Age = age;
}
Person( const Person& p)
{
cout << "Person拷贝构造函数调用" << endl;
m_Age = p.m_Age;
}
~Person()
{
cout<<"Person析构函数调用" << endl;
}
int m_Age;
};
//1 使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{
Person p1(20);
Person p2(p1);
cout << "p2的年龄为:" << p2.m_Age << endl;
}
//2 值传递的方式给函数参数传值
void doWork(Person p)
{
//因为值传递 所以会有拷贝构造函数的调用
}
void test02()
{
Person p;
doWork(p);
}
//3 以值方式返回局部对象
Person doWork2()
{
Person p1;
return p1;//值返回
}
void test03()
{
Person p = doWork2();
}
int main()
{
// test01();
// test02();
test03();
system("pause");
return 0;
}
拷贝构造函数的深拷贝与浅拷贝
C++编译器默认的拷贝构造函数,属于浅拷贝,你可以理解为简单的赋值语句,这样做可能会出错,如下所示
- 如果类中存在new操作,在堆区分配空间。
- 析构会delete掉该new操作
那么因为是简单的赋值操作,堆区空间被两个指针指向,析构时会delete两次new的空间,故产生错误。解决办法
- 重装载赋值语句(=)
- 重写拷贝构造函数,让赋值变成,重新分配新的空间,即深拷贝
这里只讨论构造函数的深拷贝与浅拷贝,后面会对深拷贝和浅拷贝做进一步的剖析。
如果我所写内容存在问题,欢迎讨论,如果有所帮助,希望点赞,收藏加关注,我们一起努力!!
原文地址:https://www.jb51.cc/wenti/3287483.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。