温故而知新四(C++)

编程入门 行业动态 更新时间:2024-10-09 22:19:10

<a href=https://www.elefans.com/category/jswz/34/1753242.html style=温故而知新四(C++)"/>

温故而知新四(C++)

创作人QQ:851301776,邮箱:lfr890207@163,欢迎大家一起技术交流,本博客主要是自己学习的心得体会,只为每天进步一点点!

个人座右铭:
1.没有横空出世,只要厚积一定发。
2.你可以学历不高,你可以不上学,但你不能不学习

一、构造函数和初始化列表

1.构造函数可以重载,也可以带有缺省参数

#include <iostream>using namespace std;//Integer(void) 和 Integer(int i)具有重载关系class Integer{
public:Integer(void){cout << "Integer(void)" << endl;m_i = 0;}//类型转换构造函数Integer(int i){cout << "Integer(int)" << endl;m_i = i;}void print(void){cout << m_i << endl;}
private:int m_i;
};int main(void)
{Integer i1;i1.print();//0Integer i2(100);i2.print();//100return 0;
}

2.缺省构造函数(无参构造函数)

1)如果类中没有定义任何构造函数,那么编译器会为其提供一个缺省构造函数:

  • 对于基本类型成员变量不做初始化
    int double等为基础类型string 等为类类型
  • 对于类 类型的成员变量(成员子对象),将自动调用相应类的无参构造函数.
class Student{
public:string m_name;//类 类型int m_age;//基本类型int m_no;//基本类型
};Student s;
cout << s.m_name << endl;//空
cout << s.m_age << endl;//未知
cout << s.m_no << endl;//未知


2)如果自己定义了构造函数,无论是否有参数,编译器都不会再提供缺省的无参构造函数了。

3.类型转换构造函数(又名单参构造函数)

class 目标类型{[explicit] 目标类型(源类型 ){...}
};

1)可以实现源类型到目标类型的转换。
2)使用explicit关键字修饰该构造函数,强制类型转换必须显式的完成.

#include <iostream>
using namespace std;
class Integer{
public:Integer(void){cout << "Integer(void)" << endl;m_i = 0;}//类型转换构造函数explicit Integer(int i){cout << "Integer(int)" << endl;m_i = i;}void print(void){cout << m_i << endl;}
private:int m_i;
};int main(void)
{Integer i1;i1.print();//0/*1)使用100作为构造实参,创建一个临时对象*2)将临时对象赋值给i1*///i1 = 100;//隐式 error//i1.print();//100//上面通过构造函数实现的隐式转换代码可读性差,推荐使用显式转换.i1 = static_cast<Integer>(200);i1.print();//i1 = (Integer)200;//C风格i1 = Integer(300);//C++风格i1.print();//300return 0;
}

4 拷贝(复制)构造函数

1)用一个已存在的对象构造同类型的副本对象,会调用该类的拷贝构造函数.

类名(const 类名& that){}class A{...};A a1;A a2(a1);//拷贝构造A a2 = a1;//和上面等价	
#include <iostream>
using namespace std;class A{
public:A(int data = 0){cout << "A(int=0)" << endl;m_data = data;}A(const A& that){cout << "拷贝构造函数" << endl;m_data = that.m_data;    }int m_data;
};int main(void)
{const A a1(100);//A a2(a1);//拷贝构造A a2 = a1;//拷贝构造cout << a1.m_data << endl;//100cout << a2.m_data << endl;//100
}

2)如果一个类没有定义拷贝构造函数,那么编译器会为该类提供一个缺省拷贝构造函数:

  • 对于基本类型的成员变量,按字节复制    
  • 对于类类型的成员变量(成员子对象),会自动调用相应类的拷贝构造函数来初始化。

注:一般不需要自己定义拷贝构造函数,因为编译器缺省提供的拷贝构造函数已经很好用了.

#include <iostream>
using namespace std;
class A{
public:A(int data = 0){cout << "A(int=0)" << endl;m_data = data;}A(const A& that){cout << "拷贝构造函数" << endl;m_data = that.m_data;    }int m_data;
};
class B{
public:A m_a;//成员子对象
};
int main(void)
{B b1;b1.m_a.m_data = 123456;B b2(b1);//拷贝构造cout << b1.m_a.m_data << endl;//123456cout << b2.m_a.m_data << endl;//123456return 0;
}
#include <iostream>using namespace std;class A{
public:A(void){cout << "A(void)" << endl;}A(const A& that){cout << "A(const A&)" << endl;}
};void foo(A a){}A bar(void){A a;//无参cout << "&a:" << &a << endl;return a;//拷贝
}
int main(void)
{A a1;//无参A a2 = a1;//拷贝foo(a1);//拷贝/* 正常情况,bar返回a拷贝到临时对象,临时* 对象再拷贝给a3,发生两次拷贝;因为编译* 器优化,让a3直接引用a,不再发生拷贝.*///去优化选项://g++ xx.cpp -fno-elide-constructorsA a3 = bar();//拷贝cout << "&a3:" << &a3 << endl;return 0;
}

 注意:-fno-elide-constructors去优化选项

3)拷贝构造函数的调用时机

  • 用已定义对象作为同类型对象的构造实参
  • 以对象形式向函数传递参数
  • 从函数中返回对象(可能会被编译器优化掉)

 5.初始化列表

1)语法形式

类名(形参表):成员变量1(初值),成员变量2(初值),...{//函数体
}
#include <iostream>using namespace std;class Student{
public:/*先定义成员变量,再赋初值Student(const string& name,int age){m_name = name;m_age = age;}*///定义成员变量同时初始化Student(const string& name,int age):m_name(name),m_age(age){}void who(void){cout << m_name << ',' << m_age << endl;}
private:string m_name;int m_age;
};int main(void)
{Student s("张飞",28);s.who();return 0;
}

 2)多数情况下使用初始化来初始化成员变量,和原来在构造函数体中赋初值没有太大区别,两者可以任选,但是在下面情况中必须要使用初始化表:
注:如果有类 类型的成员变量(成员子对象),而该类又没有无参构造函数,只能选择有参的方式来初始化该成员子对象,这时必须要使用初始化表指明其初始化方式(构造实参)

#include <iostream>using namespace std;class A{
public:A(int data){cout << "A(int)" << endl;m_data = data;}int m_data;
};class B{
public://:m_a(xx),指明成员子对象(m_a)初始化方式B(void):m_a(123456){cout << "B(void)" << endl;}A m_a;//成员子对象
};int main(void)
{B b;cout << b.m_a.m_data << endl;//123456return 0;
}

(3)const修饰的成员变量必须使用初始化表

常量:定义加初始化,在类中的时候,需要构造加初始化同步进行

(4)引用型的成员变量必须使用初始化表

#include <iostream>
using namespace std;
int num = 200;
class A{
public:/*A(void){m_c = 100;m_r = num;}*/A(void):m_c(100),m_r(num){}const int m_c;int& m_r;
};
int main(void)
{A a;cout << a.m_c << ',' << a.m_r << endl;return 0;
}

 (5)成员变量的初始化顺序由声明的顺序决定,而与初始化无关

错误示范(先声明的m_len,初始化先初始化m_len,此时m_str为NULL):

 改正方式:

第一种调整m_str和m_len的声明先后顺序

 调整声明的先后顺序,这个方法不好。

第二种方式:判断形参的长度

 相对前一种较好

第三种:采用三目描述符,并判断异常

 采用三目,并判断异常,方案最优。

 注:如果类中的成员是类类成员,先构造子对象(调用类中的类类成员构造函数),在构建自己构造函数

更多推荐

温故而知新四(C++)

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

发布评论

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

>www.elefans.com

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