【C++grammar】代理构造、不可变对象、静态成员

标签: C++ grammar  c++  

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:setter
    e.setBirthday(Date(1999,1,1));
    std::cout << e.toString() << std::endl;
    //2:getter
    e.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关键字用法详解

版权声明:本文为qq_42604176原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42604176/article/details/109515629

智能推荐

【教程向】通过windows在树莓派3B上安装Ubuntu MATE 16.04.2 (Xenial)

本文参考了http://www.ituring.com.cn/article/273613 ================================================================= 1:因为树莓派3B的性能问题,所以使用这个特别为树莓派设计的版本。 2:准备: 树莓派3B * 1 16GB TF/Micro SD卡 *1(尽量用速度快一些的卡,因为以后这相...

LeetCode(7 整数反转)

如题 这就不用分析了,直接依次取每位即可,难点就是个越界判断...

Caused by: java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception

启动RMI报如下错误: 最后发现是端口冲突造成的,当时用的5003端口启动服务端的RMI刚好和本地的一个服务端口冲突。 输入netstat -aon|findstr "5003"查询它的pid为3056 继续输入tasklist|findstr "3056",查看是哪个进程或者程序占用了5003端口,结果是:magentproc.exe 找到PID后可以直接...

【LeetCode(Java) - 322】零钱兑换

文章目录 1、题目描述 2、解题思路 3、解题代码 1、题目描述 2、解题思路   定义 dp[i] 表示对于组成金额 i 的最少硬币个数。   如果方案存在,那么至少有一个硬币至少出现了一次:   如果是第 0 个硬币出现了一次,则:dp[i] = dp[i-coins[0]] + 1   如果是第 1 个硬币出现了...

在Visual Studio 2013中配置Entity Framework使用MySQL

环境 使用的软件及版本 - Microsoft Visual Studio Ultimate 2013 (版本 12.0.40629.00 Update 5) - Microsoft.Net Framework 版本 4.6.01055 - MySQL版本: 5.6.17 步骤 1. 创建空的MVC项目 2. 安装扩展 3. 在数据库中建立对应的表 必须在数据库内先新建表,否则asp.net mv...

猜你喜欢

Python才是世界上最好的言语,php,java靠边站

伟大的入门编程语言有什么特征呢?或者换一种方式问,“当我们教他们编程时,应该给予他们什么?”对于成年人和青少年学生,我认为以下五点非常重要。 学生从入门语言获得的五样东西 非常棒的首次体验,就像一本书的第一页,首先需要“入迷”,学习新知识不可避免的会遇到挫折,但要有持续的热情和好奇心,这对于那些从未接触过编码的年轻人来说是至关重要的; Web编程的能...

动态调整docker容器cpu资源

目的:动态调整系统cpu核数后,如何在不停止容器服务的情况下,docker动态使用最新的CPU资源 事件由来:     1、在ucloud上购买了一台可以热升级的机器,热升级指的是动态更改系统cpu和内存资源     2、随着业务的扩展,发现cpu、内存负载过高,需要在不停止业务的情况下动态扩容,因此使用了ucloud提供的热升级服务,从4核12G扩容为8核...

用python itchat包 爬取微信好友头像形成矩形头像集

原创作品,转载请注明作者 abysscarry-袁杰丶 初学python,我们必须干点有意思的事!从微信下手吧! 头像集样例如下: 大家可以发朋友圈开启辨认大赛哈哈~ 话不多说,直接上代码,注释我写了比较多,大家应该能看懂 运行结果: ok!!!...

impala实现拉链表

1.文档目的         拉链表是针对数据仓库设计中表存储数据的方式而定义的,即是记录历史。记录一个事物从开始,一直到当前状态的所有变化的信息。传统数据仓库一般采用拉链的方式保留主数据(例如客户信息)的变化数据,采用这种设计方式的主要原因是减少数据冗余。这个需求在Hadoop中主要是有以下两种实现方式选择: 每天保留一份全量的切片数据。Hadoop平台由...

Codeforce 975E

E. Hag's Khashba time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard output Hag is a very talented person. He has always had an artist inside him but his...