首页 > 其他分享 >构造函数

构造函数

时间:2024-05-25 14:56:07浏览次数:21  
标签:初始化 int 列表 constexpr MyClass 构造函数

类成员初始化

方式:
1、通过构造函数的参数列表初始化。
2、在构造函数中赋值完成初始化。

//1、通过构造和函数的参数列表初始化
Seles_data::Sales_data(const Sales_data &sa)
{
	this->bookNo = sa.bookNo;
	this->revenue = sa.revenue;
	this->units_sold = sa.units_sold;
}

但不是所有成员都可以通过构造函数内赋值完成初始化,比如const,引用类型的成员变量。这种类型需要用构造函数初始化列表进行初始化。

//2、构造函数中赋值完成初始化
class ConstRef
{
public:
	ConstRef(int ii) : ci(ii), ri(ii)
	{
		i = ii;
	}
private:
	int i;
	const int ci;
	int &ri;

}

补充:构造函数初始值列表

构造函数初始值列表,是一种用于初始化类成员变量的机制。
它可以在构造函数体执行之前,以一种高效的方式对成员变量进行初始化。
这种初始化方式尤其适合初始化非静态成员变量和基类对象。

基本语法:
构造函数初始值列表紧跟在构造函数声明的参数列表之后,用冒号引入,并用逗号分割各个初始化操作。
每个初始化操作指定了成员变量或基类对象以及它们的初始化表达式。

ClassName::ClassName(参数) : member1(初始化表达式), member2(初始化表达式) {}

委托构造函数

是C++11引入的新特性。
它允许一个构造函数调用同一个类的另一个构造函数来完成初始化的过程。
这种机制可以避免代码的重复,特别是在处理具有多个构造函数且这些构造函数之间有许多共通初始化任务时。

基本语法:

class MyClass {
public:
    // 构造函数A
    MyClass(int a) : memberA(a) {
        // 初始化代码A
    }
    // 构造函数B,委托给构造函数A
    MyClass() : MyClass(0) {
        // 初始化代码B
    }
private:
    int memberA;
};

在这个例子中,Myclass()构造函数(构造函数B)委托给了MyClass(int a)构造函数(构造函数A),通过传递一个默认值0。
这意味着,当使用构造函数B创建对象时,它首先会调用构造函数A来完成一部分初始化任务,然后再执行自己的初始化代码。

委托流程

  1. 委托调用:委托构造函数在初始化列表中直接调用另一个构造函数。
  2. 顺序执行:被委托的构造函数先执行其初始化列表和函数体中的初始化代码。
  3. 继续执行:然后控制权返回给委托的构造函数,继续执行其函数体中的初始化代码。
    使用场景
    委托构造函数适用于以下场景:
  • 避免代码重复:当多个构造函数需要执行相同的初始化代码时。
  • 简化代码:简化复杂的构造函数,提高代码的可读性和可维护性。
  • 层次化初始化:按照不同的初始化层次和步骤,逐步完成对象的构建。
    注意事项
  • 避免循环委托:构造函数不能无限循环地相互委托,否则会导致编译错误。
  • 委托给其他构造函数:委托构造函数可以委托给类内定义的任何其他构造函数,包括私有构造函数。

转换构造函数

是一种特殊的构造函数,它允许将一个其他类型的对象隐式或显式地转换为当前类的对象。
这种构造函数在实现类型转换时非常有用,可以增强代码的灵活性和可读性。

基本形式:

class MyClass {
public:
    // 转换构造函数
    MyClass(const OtherClass& other) {
        // 转换逻辑
    }
};

这里,MyClass类的构造函数接收一个OtherClass类型的常量引用作为参数。
这意味着,当你尝试用一个OtherClass对象初始化一个MyClass对象时,或者将一个OtherClass对象赋值给一个MyClass对象时,这个转换构造函数会被自动调用。

使用场景:

  • 隐式类型转换:当需要从一个类型隐式转换为另一个类型时。比如:从一个自定义的时间类转换为内置的int类型表示时间戳。
  • 显式类型转换:通过关键字explicit来防止隐式转换,增加代码的安全性。

示例:

//厘米类
class Centimeter
{
public:
	Centimeter(double v) : value(v){}	//构造函数初始值列表
	double getValue() const
	{
		return value;
	}
private:
	double value;
};

//米类
class Meter
{
public:
	//转换构造函数
	Meter(cosnt Cenetimeter& cm) : value(cm.getValue() / 100.0){}	//构造函数初始值列表
private:
	double value;
};

int main()
{
	Centimeter cm(500);	//cm为500厘米
	Meter m = cm;		//隐式类型转换,将cm的500厘米转为5米
	return 0;

}

explicit 关键字

用于修饰一个类的构造函数,目的是防止构造函数被用于隐式类型转换,
也就是说:使用explicit 关键字可以强制构造函数只能用于显式类型转换。

基本语法:

class MyClass
{
public:
	//显式构造函数
	explicit MyClass(int value) : data(value) {}	//构造函数初始值列表
private:
	int data;
}

聚合类

使得用户可以直接访问其成员,并且具有特殊的初始化语法形式。
当一个类满足以下条件时,我们说它是聚合的:
1、所有成员都是public的;
2、没有定义任何构造函数;
3、没有类内初始值;
4、没有基类,也没有virtual函数。

以下是聚合类:

struct Data
{
	int ival;
	string s;
}

可以用初始化{}来初始化聚合类:

Data val2 = {0, "xiaohe"};

初始值的顺序必须与声明的顺序一致。
初始值列表的元素个数绝对不能超过类的成员数量。

constexpr关键字

C++11引入constexpr关键字。
允许在编译时计算表达式,这不仅适用于变量和函数,也适用于构造函数。constexpr 构造函数可以用于创建 constexpr 对象,这些对象在编译时就能被初始化,从而在需要常量表达式的地方使用。

constexpr构造函数的条件
要使构造函数成为 constexpr,它必须满足以下条件:

  1. 返回类型:构造函数不能有返回类型(因为构造函数返回的是正在构造的对象)。
  2. constexpr函数体:构造函数的函数体必须是 constexpr,这意味着它只能包含初始化列表和一条返回语句(或者没有返回语句,因为构造函数隐式地返回其正在构造的对象)。
  3. constexpr参数:所有参数必须是可以 constexpr 计算的。
  4. 成员初始化:所有成员变量必须通过构造函数的初始化列表进行初始化。

示例:

class Vector2D {
public:
    constexpr Vector2D(double xVal = 0, double yVal = 0) : x(xVal), y(yVal) {}
    constexpr double magnitude() const { return sqrt(x * x + y * y); }
private:
    double x, y;
};
constexpr Vector2D globalVec(3.0, 4.0); // 编译时初始化
int main() {
    constexpr Vector2D localVec(5.0, 12.0); // 编译时初始化
    constexpr double length = localVec.magnitude(); // 编译时计算
    return 0;
}

在这个例子中,Vector2D 的构造函数被声明为 constexpr,允许我们使用该构造函数在编译时创建 constexpr 对象(如 globalVec 和 localVec)。此外,magnitude 函数也是 constexpr,允许在编译时计算向量的长度。

使用场景

  • 编译时常量:当需要在编译时创建和使用常量对象时,constexpr 构造函数非常有用。
  • 模板元编程:在模板元编程中,constexpr 构造函数允许在编译时执行更复杂的操作,如计算数组的大小或执行数学计算。
  • 接口一致性:在库或框架开发中,提供 constexpr 构造函数可以提高接口的一致性,使得用户可以在需要常量表达式的地方使用你的类。

标签:初始化,int,列表,constexpr,MyClass,构造函数
From: https://www.cnblogs.com/H43724334/p/18212324

相关文章

  • 拷贝构造函数
    简介是一个特殊的构造函数,只有一个形参,该形参常用const修饰,是对该类型的引用。当定义一个新的对象并用一个同类型的对象对它进行初始化时,用显式拷贝构造函数。当该类型的对象传递给函数或从函数返回类型的对象时,用隐式拷贝构造函数。拷贝构造函数拷贝构造函数通常用于:1、通......
  • 不同场景下的构造函数调用
    本文为对不同场景下的构造函数调用进行跟踪。构造函数默认情况下,在C++之后至少存在六个函数默认构造/析构函数,复制构造/复制赋值,移动构造/移动赋值。以下代码观测发生调用的场景#include<iostream>structFoo{Foo():fd(0){std::cout<<"Foo::Foo()this="<<......
  • c++ 结构体的构造函数
    结构体中构造函数1、不使用构造函数1#include<iostream>23structstudent{45intage;6std::stringgender;78}Liu;910intmain(){11Liu.age=20;12Liu.gender="man";1314std::cout<<Liu.age<......
  • 结构体中的指针&&拷贝赋值构造函数改造
    带有成员指针的结构体的拷贝1.问题使用结构体时,在析构时发生了**重复释放指针**的错误。2.原因定义了QList<结构体>,使用append添加结构体对象并未此结构体中的指针分配了空间,append会执行值拷贝,此时会创建新的副本添加进QList中,值得注意的是:append执行拷贝时并不会分配地......
  • 构造函数的成员初始化列表
    为什么要初始化成员对于类成员是基础数据类型,例如int、char这些,构造对象时,成员不会被初始化,值是随机的。下面代码可以验证下:classA{public:A(){}voidshowMember()const{std::cout<<"a:"<<a<<std::endl;}private:inta;};int......
  • js的函数及无参与有参构造函数
    1.函数定义fuctionfn(str){//1.定义函数alert(str);}fn("测试方法");varfn1=function(str){//2.定义函数alert(str);}varfn2=fuction(f,str){f(str);}fn2(fn1,"方法作为参数");//函数可以作为方法传递参数2.无参构造:varperson=function(){alert("......
  • C++ 构造函数实战指南:默认构造、带参数构造、拷贝构造与移动构造
    C++构造函数构造函数是C++中一种特殊的成员函数,当创建类对象时自动调用。它用于初始化对象的状态,例如为属性分配初始值。构造函数与类同名,且没有返回值类型。构造函数类型C++支持多种类型的构造函数,用于满足不同的初始化需求:默认构造函数:不带参数的构造函数,通常用于初......
  • 默认构造函数学习
    转自:https://blog.csdn.net/sevenjoin/article/details/88314531,讲的很好。1.介绍若针对一个类没有显式地定义构造函数,那么编译器会隐式的为这个类生成一个默认构造成员函数。 默认构造函数就是在调用时不需要显示地传入实参的构造函数。假如用户定义了其他构造函数(比如有参数......
  • 构造函数与析构函数
    构造函数可以有多个,可以重载复制构造函数只有一个参数,即对同类对象的引用没有定义会生成默认复制构造函数Complex(constComplex&c){ real=c.real; imag=c.imag;}三种使用情况用对象去初始化同类的另一个对象Complexc2(c1);函数有一个参数是类A是的对象时......
  • 深入分析C++对象模型之移动构造函数
    接下来我将持续更新“深度解读《深度探索C++对象模型》”系列,敬请期待,欢迎关注!也可以关注公众号:iShare爱分享,自动获得推文和全部的文章列表。C++11新标准中最重要的特性之一就是引入了支持对象移动的能力,为了支持移动的操作,新标准引入了一种新的引用类型——右值引用,右值引用一......