18 CPP构造函数和析构函数

编程入门 行业动态 更新时间:2024-10-24 04:43:58

18 CPP构造<a href=https://www.elefans.com/category/jswz/34/1771370.html style=函数和析构函数"/>

18 CPP构造函数和析构函数

18 CPP构造函数和析构函数

1)构造函数

语法:类名(){.....}

1 访问权限一般是public,有时候可以设置为private,比如单例的时候

2 函数名称必须与类名相同

3 没有返回值,也不写void

4 可以有参数,可以重载,可以有默认参数

5 创建对象时会自动调用一次,不能手工调用。

2)析构函数

语法:~类名(){....}

1 访问权限一般是public,有时候可以设置为private

2 函数名称必须与类名相同,且加~

3 没有返回值,也不写void

4 没有参数,不能重载

5 销毁对象时会自动调用一次,但是可以手工调用。

手动调用析构函数

#include <iostream>using namespace std;class Person {
public:~Person() {cout << "调用了析构函数" << endl;}
};void test() {Person p;p.~Person();//手动调用析构函数
}int main() {test();return 0;
}
//调用了析构函数
//调用了析构函数

注意:

1 如果没有提供构造/析构函数,编译器将提供空实现的构造/析构函数。

2 如果提供了构造/析构函数,编译器将不提供空实现的构造/析构函数。

3 创建对象的时候,如果重载了构造函数,编译器根据实参匹配相应的构造函数,没有参数的构造函数也叫默认构造函数。

4 创建对象的时候不要再对象名后面加空的圆括号,编译器误认为是声明函数。(如果没有构造函数、构造函数没有参数、构造函数的参数都有默认参数)(后面有说明)

5 在构造函数名后面加括号和参数不是调用构造函数,是创建匿名对象。 (后面有说明)

6 接受一个参数的构造函数允许使用赋值语法将对象初始化为一个值(可能会导致问题,不推荐)(后面有说明)

7 以下两行代码有本质的区别:

Person p = Person("hello", 20);//显示创建对象Person p;//创建对象
p = Person("hello", 20);//创建匿名对象,然后给现有的对象赋值

8 用new/delete 创建/销毁对象时,也会调用构造函数/析构函数。

9 不建议在构造/析构函数中写太多工作(只能成功不会失败,因为没有返回值)

10 除了初始化,不建议让构造函数做太多工作(只能成功不会失败)

11 c++11支持使用统一初始化列表 (后面有说明)

12 如果类的成员也是类,创建对象的时候,先构造成员类;销毁对象时,先析构成员类。

4 创建对象的时候不要再对象名后面加空的圆括号,编译器误认为是声明函数。(如果没有构造函数、构造函数没有参数、构造函数的参数都有默认参数)的代码演示

#include <iostream>
#include <cstring>using namespace std;//创建对象的时候不要再对象名后面加空的圆括号,编译器误认为是声明函数。
// (如果没有构造函数、构造函数没有参数、构造函数的参数都有默认参数)
class Person {
public:Person() {m_Name.clear();m_Age = 0;memset(m_Hobby, 0, sizeof(m_Hobby));}Person(string name) {m_Name = name;m_Age = 0;memset(m_Hobby, 0, sizeof(m_Hobby));cout << "调用了构造函数" << endl;}Person(string name, int age) {m_Name = name;m_Age = age;memset(m_Hobby, 0, sizeof(m_Hobby));cout << "调用了构造函数" << endl;}void show() {cout << "show" << endl;}~Person() {cout << "调用了析构函数" << endl;}private:string m_Name;int m_Age;char m_Hobby[30];
};void test() {Person p();//编译不会报错
//    编译warning如下 empty parentheses interpreted as a function declaration
//意思就是 空括号被解释为函数声明
//    p.show();//调用不了
//其实Person p();的意思是声明一个函数返回值为Person的函数,函数名叫p
}int main() {test();return 0;
}

5 在构造函数名后面加括号和参数不是调用构造函数,是创建匿名对象。的代码演示

#include <iostream>using namespace std;class Person {
public:Person() {m_Name.clear();m_Age = 0;memset(m_Hobby, 0, sizeof(m_Hobby));
//        cout << "调用了构造函数Person() " << endl;}Person(string name) {Person();m_Name = name;
//        m_Age = 0;
//        memset(m_Hobby, 0, sizeof(m_Hobby));
//        cout << "调用了构造函数Person(string name)" << endl;}Person(string name, int age) {Person();m_Name = name;m_Age = age;
//        memset(m_Hobby, 0, sizeof(m_Hobby));
//        cout << "调用了构造函数Person(string name, int age)" << endl;}void show() {cout << "姓名:" << m_Name << ",年龄:" << m_Age << " 兴趣:" << m_Hobby << endl;}~Person() {
//        cout << "调用了析构函数" << endl;}private:string m_Name;int m_Age;char m_Hobby[30];
};void test() {Person p("kobe", 22);p.show();
}int main() {test();return 0;
}
/**调用输出内容为:
姓名:kobe,年龄:22 兴趣:�如果粗心的人,这事就这么过了,留下巨大的bug,因为没有调用构造函数16行 24行的 Person(); 的真正含义不是调用构造函数,而是创建一个匿名对象,也叫临时对象临时对象的特点,没有名字,创建之后立马就销毁(;后面就开始销毁)*/

 证明下创建后就销毁了。启用打印日志

#include <iostream>using namespace std;class Person {
public:Person() {m_Name.clear();m_Age = 0;memset(m_Hobby, 0, sizeof(m_Hobby));cout << "调用了构造函数Person() " << endl;}Person(string name) {Person();m_Name = name;
//        m_Age = 0;
//        memset(m_Hobby, 0, sizeof(m_Hobby));
//        cout << "调用了构造函数Person(string name)" << endl;}Person(string name, int age) {cout << "start" << endl;Person();cout << "end" << endl;m_Name = name;m_Age = age;
//        memset(m_Hobby, 0, sizeof(m_Hobby));
//        cout << "调用了构造函数Person(string name, int age)" << endl;}void show() {cout << "姓名:" << m_Name << ",年龄:" << m_Age << " 兴趣:" << m_Hobby << endl;}~Person() {cout << "调用了析构函数" << endl;}private:string m_Name;int m_Age;char m_Hobby[30];
};void test() {Person p("kobe", 22);p.show();
}int main() {test();return 0;
}
/**调用输出内容为:
start
调用了构造函数Person()
调用了析构函数
end
姓名:kobe,年龄:22 兴趣:�
调用了析构函数可以从上面输出结果看出
start
调用了构造函数Person()
调用了析构函数
end上面输出是25行 Person();  临时对象 创建和销毁时调用的*/

构造函数没被调用,后果就很难说了,这个要看你的类里面有什么数据类型了,上面的例子不调用构造函数问题不大,如果类里面有指针,那就很危险了。

视频里面说的是:(他的环境是VS)

如下面的代码,加入m_ptr指针,如果构造函数没有被调用,指针不会初始化为空,并且别的地方也没有为指针分配内存,那么m_ptr就是野指针了,然后析构里面的delete m_ptr可能会让程序崩溃。

但是我g++ 测试 delete 没问题

m_ptr默认就是0x0

#include <iostream>
#include <cstring>
using namespace std;class Person
{
public:Person(){m_Name.clear();m_Age = 0;m_ptr = nullptr;memset(m_Hobby, 0, sizeof(m_Hobby));cout << "调用了构造函数Person() 1" << endl;}Person(string name){Person();m_Name = name;//        m_Age = 0;//        memset(m_Hobby, 0, sizeof(m_Hobby));//        cout << "调用了构造函数Person(string name)" << endl;}Person(string name, int age){cout << "start" << endl;Person();cout << "end" << endl;m_Name = name;m_Age = age;//        memset(m_Hobby, 0, sizeof(m_Hobby));//        cout << "调用了构造函数Person(string name, int age)" << endl;}void show(){cout << "姓名:" << m_Name << ",年龄:" << m_Age << " 兴趣:" << m_Hobby << endl;}~Person(){//        delete m_ptr;//直接写也行,因为对空指针delete是安全的cout << m_ptr << endl;if (m_ptr != nullptr){ // 这样写也行delete m_ptr;m_ptr = nullptr;}cout << "调用了析构函数" << endl;}private:string m_Name;int m_Age;char m_Hobby[30];int *m_ptr;
};void test()
{Person p("kobe", 22);p.show();
}int main()
{test();return 0;
}
/*
start
调用了构造函数Person() 1
0x0
调用了析构函数
end
姓名:kobe,年龄:22 兴趣:
0x0
调用了析构函数*/

6 接受一个参数的构造函数允许使用赋值语法将对象初始化为一个值(可能会导致问题,不推荐)

#include <iostream>using namespace std;class Person {
public:Person() {m_Name.clear();m_Age = 0;m_ptr = nullptr;memset(m_Hobby, 0, sizeof(m_Hobby));}Person(string name) {m_Name = name;m_Age = 0;m_ptr = nullptr;memset(m_Hobby, 0, sizeof(m_Hobby));}Person(int age) {m_Name.clear();m_Age = age;m_ptr = nullptr;memset(m_Hobby, 0, sizeof(m_Hobby));}void show() {cout << "姓名:" << m_Name << ",年龄:" << m_Age << " 兴趣:" << m_Hobby << endl;}~Person() {
//        delete m_ptr;//直接写也行,因为对空指针delete是安全的cout << m_ptr << endl;if (m_ptr != nullptr) {//这样写也行delete m_ptr;m_ptr = nullptr;}cout << "调用了析构函数" << endl;}private:string m_Name;int m_Age;char m_Hobby[30];int *m_ptr;
};void test() {Person p = string("hello");p.show();Person p2 = 11;p2.show();
}int main() {test();return 0;
}
/*
姓名:hello,年龄:0 兴趣:
姓名:,年龄:11 兴趣:
0x0
调用了析构函数
0x0
调用了析构函数*/

11 c++11支持使用统一初始化列表

#include <iostream>using namespace std;class Person {
public:Person() {m_Name.clear();m_Age = 0;m_ptr = nullptr;memset(m_Hobby, 0, sizeof(m_Hobby));cout << "调用构造函数Person()" << endl;}Person(string name, int age) {m_Name = name;m_Age = age;m_ptr = nullptr;memset(m_Hobby, 0, sizeof(m_Hobby));cout << "调用构造函数Person(string name, int age)" << endl;}void show() {cout << "姓名:" << m_Name << ",年龄:" << m_Age << " 兴趣:" << m_Hobby << endl;}~Person() {cout << "调用了析构函数" << endl;}private:string m_Name;int m_Age;char m_Hobby[30];int *m_ptr;
};void test() {Person p = {"hello", 19};Person p2{"hello", 19};Person *ptr = new Person{"hello", 19};
}int main() {test();return 0;
}
/**/

更多推荐

18 CPP构造函数和析构函数

本文发布于:2024-03-05 14:20:07,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1712528.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   CPP

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!