【C++grammar】代理构造、不可变对象、静态成员
目录
- 1、Delegation Constructor(代理构造)
- 1. What is delegating constructor? (什么是代理构造/委托构造)
- 2. Avoiding recursive calls of target constructors (避免递归调用目标ctor)
- 3. 委托构造的好处
- 2、不可变对象和类
- 1、如何让类成为“不可变类”
- 2、特殊情况:指针成员
- 3、例子
- 4、不可变对象的“不可变”特征在软件开发中有什么用? 它和thread-safe有什么关系?
- 3、不可变对象和类
- 1、声明或定义静态成员
- 2、静态成员
- 3、实例成员和静态成员
- 4、C 中static的作用
1、Delegation Constructor(代理构造)
1. What is delegating constructor? (什么是代理构造/委托构造)
代理构造:一个构造函数可以调用另外的构造函数
在代理构造的时候,被委托的要放在委托的构造函数的初始化列表的位置,不能放在在括号里面。
class A{public: A(): A(0){}A(int i): A(i, 0){}A(int i, int j) {num1=i;num2=j;average=(num1+num2)/2;}
private:int num1;int num2;int average;
};
上面例子中,构造函数的调用次序:
A() ->A(int) ->A(int, int)
在这个过程中,形成了所谓的委托构造量,我们最怕的就是出现环形的委托构造。
2. Avoiding recursive calls of target constructors (避免递归调用目标ctor)
递归调用:函数调用其本身
递归调用实际上就是环形调用。
class A{public: A(): A(0){}A(int i): A(i, 0){}A(int i, int j): A(){}
private:int num1;int num2;int average;
};
调用次序:
A() -> A(int) ->A(int, int) ->A()
3. 委托构造的好处
让程序员少写代码,使逻辑更加清晰。
执行程序时, 会先执行 一个参数的构造函数, 然后再执行两个参数的构造函数。
大大减少了代码量。
2、不可变对象和类
不可变对象:对象创建后,其内容不可改变,除非通过成员拷贝
不可变类:不可变对象所属的类
1、如何让类成为“不可变类”
1、所有数据域均设置为“私有”属性
2、没有更改器函数
3、也没有能够返回可变数据域对象的引用或指针的访问器
如下:
2、特殊情况:指针成员
如果只有下面两个条件,是构成不了不可变类的。
1、所有数据域均设置为“私有”属性
2、没有更改器函数
如果getter函数返回指向成员的指针,或者getter函数返回成员的引用。那么通过getter函数也能够修改类成员。
如下:指针指向了类的私有成员,然后我们修改对象的私有数据成员,让对象不成为不可变类。
所以才要加入第三个条件:没有能够返回可变数据域对象的引用或指针的访问器
3、例子
#include<iostream>
#include<string>
using namespace std;class Date {private:int year = 2019, month = 1, day = 1;
public:int getYear() { return year; }int getMonth() { return month; }int getDay() { return day; }void setYear(int y) { year = y; }void setMonth(int m) { month = m; }void setDay(int d) { day = d; }Date() = default;Date(int y, int m, int d) :year(y), month(m), day(d) {}std::string toString() {return (std::to_string(year) + '-' + std::to_string(month) + '-' + std::to_string(day));}
};enum class Gender {male,female,
};class Employee {private:std::string name;Gender gender;Date birthday;
public:void setName(std::string name) { this->name = name; }void setGender(Gender gender) { this->gender = gender; }void setBirthday(Date birthday) { this->birthday = birthday; }std::string getName() { return name; }Gender getGender() { return gender; }Date* getBirthday() { return &birthday; }std::string toString(){return (name +( (gender == Gender::male ? std::string(" male ") : std::string(" female ") )+ birthday.toString()));}//带参构造函数Employee(std::string name,Gender gender,Date birthday):name{name},gender{gender},birthday{birthday}{}//默认构造函数Employee():Employee("Alan",Gender::male,Date(2000,4,1)){}
};//创建Employee对象,然后修改其生日
int main()
{Employee e;//1:settere.setBirthday(Date(1999,1,1));std::cout << e.toString() << std::endl;//2:gettere.getBirthday()->setYear(1998);std::cout << e.toString() << std::endl;return 0;
}
4、不可变对象的“不可变”特征在软件开发中有什么用? 它和thread-safe有什么关系?
将一些需要共享和协同开发的内容设为不可变对象可以防止内容被他人修改。起到类似const的作用。
详细可以观看这篇文章:
线程安全ThreadSafe
3、不可变对象和类
1、声明或定义静态成员
在类定义中,关键字 static 声明 不绑定到类实例的成员( 该成员无需创建实例化对象即可访问,可以直接用类去访问)在类的内部声明
静态成员的定义是很复杂的。
静态数据成员定义的规则:
(1) 声明为“constexpr”类型的静态数据成员必须 在类中声明 并初始化。自C++17 起,可不在类外定义
(2) 声明为==“inline”(C++17 起) 或者 “const int” == 类型的静态数据成员可以 在类中声明 并初始化;
(3) 其它须在类外 定义并初始化,且不带static 关键字
静态数据成员的定义规则复杂,在类外定义,大部分情况下不会出错
2、静态成员
静态数据成员具有静态存储期(static storage duration)或者C++11线程存储期特性。
静态存储期
对象的存储在程序开始时分配,而在程序结束时解回收。
(1) Only one instance of the object exists ( 只存在对象的一个实例)
(2) 静态存储器对象未明确初始化时会被自动“零初始化(Zero-Initialization)”
3、实例成员和静态成员
一旦实例化了Square(创建了Square的对象),每个对象中都有各自的side成员。这个side成员就叫做实例成员。
而numberOfObjects只存在一个,是由所有的Square对象共享的,叫做静态成员。
class Square {private:double side;static int numberOfObjects;// ...
public://代理构造,无参构造函数调用有参构造函数Square():Square(1.0){}Square(double side){this->side = side;numberOfObjects++;}// ...
};
//定义静态数据成员,会被零初始化
int Square::numberOfObjects;
int main() {Square s1{}, s2{5.0};
}
调用一次构造函数,numberOfObjects就会+1,所以numberOfObjects可以统计成员数量
4、C 中static的作用
c语言中static关键字用法详解
【C++grammar】代理构造、不可变对象、静态成员相关推荐
- java 不允许默认构造_java – 如何使用ObjectMapper去除/序列化不可变对象而不使用默认构造函数?...
我想使用com.fasterxml.jackson.databind.ObjectMapper对不可变对象进行序列化和反序列化. 不可变类看起来像这样(只有3个内部属性,getter和construc ...
- 并发编程-10线程安全策略之不可变对象
文章目录 脑图 四个线程安全策略 不可变对象定义 不可变对象需要满足的条件 如何创建不可变对象 使用final关键字定义不可变对象 修饰变量示例 final修饰基本数据类型及String: 初始化之后 ...
- 高并发学习(二)安全发布对象/不可变对象/线程封闭
线程安全的途径: 安全发布对象-发布与逃逸 发布对象:使一个对象能够被当前范围之外的代码所使用 对象逃逸:一种错误的发布.当一个对象还没有构造完成的,就使它被其他线程所见 安全发布对象(单例模式:列一 ...
- 可变对象 不可变对象区别_对象应该是不可变的
可变对象 不可变对象区别 在面向对象的编程中,如果对象的状态在创建后无法修改,则它是不可变的 . 在Java中,不可变对象的一个很好的例子是String . 创建后,我们无法修改其状态. 我们可以 ...
- python中不可变对象_Python中的可变对象与不可变对象、浅拷贝与深拷贝
Python中的对象分为可变与不可变,有必要了解一下,这会影响到python对象的赋值与拷贝.而拷贝也有深浅之别. 不可变对象 简单说就是某个对象存放在内存中,这块内存中的值是不能改变的,变量指向这块 ...
- Java™ 教程(不可变对象)
不可变对象 如果一个对象的状态在构造后不能改变,则该对象被认为是不可变的,对不可变对象的最大依赖被广泛认为是一种创建简单.可靠代码的合理策略. 不可变对象在并发应用程序中特别有用,由于它们不能改变状态 ...
- java中不可变对象(immutable object)是什么,有什么意义
不可变对象顾名思义不可改变的对象 一旦构造器完成执行,该实例即无法改变 意味着可以传递对象的引用,不用担心改变其内容,特别是在处理并行时,不可变对象不存在锁的问题,易于构造使用 final class ...
- Java-可变对象和不可变对象介绍
一.简单定义 不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能改变,反之即为可变对象(Mutable Objects). 不可变对象的类即为 ...
- python列表是可变对象吗_Python可变对象和不可变对象
Python中一切皆对象,每个对象都有其唯一的id,对应的类型和值,其中id指的是对象在内存中的位置.根据对象的值是否可修改分为可变对象和不可变对象.其中, 不可对象包括:数字,字符串,tuple 可 ...
最新文章
- CornerNet代码解析——损失函数
- 国贫县山西永和:“一揽子”保险“保”脱贫
- 一文理解微服务架构下的系统可用性如何保证?
- 批量设置Service Order成transferred状态
- praying,blessing,wishing
- CF1119G. Get Ready for the Battle
- vsftpd安装问题汇总(持续更新。。)
- 轻松掌握Redux-Action使用方法
- View绑定式监听器实现原理
- Nginx基本数据结构之ngx_list_t
- 羽毛球 vs. 软件开发
- css transition transform animation例子讲解
- python特征数据类型及常用操作对比总结_如何全面解析数据并创造数据故事
- Python课程入门之Pycharm创建PY文件的使用步骤与模板创建
- PAT_乙级_1001_筱筱
- 时间、空间、对象 海量极速多维检索 - 阿里云RDS PostgreSQL最佳实践
- 手机扫描证件识别的优势
- RAD Studio C++ Builder10.4 补丁Patch 2仍然没有彻底解决C ++ Android异常处理错误
- 五线城市房价已大幅下跌,房地产泡沫破裂或由此开始
- 构建一个类book,其中含有2个私有数据成员qu和price,建立一个有5个元素的数组对象,将qu初始化为1~5,将price初始化为qu的10倍。