0
点赞
收藏
分享

微信扫一扫

Kafka-exporter监控消费速度与生产速度差异规则

目录

4 类和对象

4.2 对象的初始化和清理

4.2.1 构造函数和析构函数

4.2.2 构造函数的分类及调用

4.2.3 拷贝构造函数调用时机

4.2.4 构造函数调用规则

4.2.5 深拷贝与浅拷贝

4.2.6 初始化列表

4.2.7 类对象作为类成员

4.2.8 静态成员 

示例1:静态成员变量

示例2:静态成员函数


4 类和对象

C++面向对象的三大特性为:封装、继承、多态
C++认为万事万物都皆为对象,对象上有其属性和行为
例如:
        人可以作为对象,属性有姓名、年龄、身高、体重..,行为有走、跑、跳、吃饭、唱歌..

        车也可以作为对象,属性有轮胎、方向盘、车灯…行为有载人、放音乐、放空调....

        具有相同性质的对象,我们可以抽象称为类,人属于人类,车属于车类

4.2 对象的初始化和清理
  • 生活中我们买的电子产品都基本会有出厂设置,在某一天我们不用时候也会删除一些自己信息数据保证安全。
  • C++中的面向对象来源于生活,每个对象也都会有初始设置以及 对象销毁前的清理数据的设置。
4.2.1 构造函数和析构函数

对象的初始化和清理也是两个非常重要的安全问题

  •         一个对象或者变量没有初始状态,对其使用后果是未知
  •         同样的使用完一个对象或变量,没有及时清理,也会造成一定的安全问题

c++利用了构造函数和析构函数解决上述问题,这两个函数将会被编译器自动调用,完成对象初始化和清理工作。对象的初始化和清理工作是编译器强制要我们做的事情,因此如果我们不提供构造和析构,编译器会提供编译器提供的构造函数和析构函数是空实现

  • 构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
  • 析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。

 构造函数语法:类名(){}
1.构造函数,没有返回值也不写void
2.函数名称与类名相同
3.构造函数可以有参数,因此可以发生重载
4.程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次

 析构函数语法:~类名(){}
1.析构函数,没有返回值也不写void
2.函数名称与类名相同,在名称前加上符号 ~
3.析构函数不可以有参数,因此不可以发生重载
4.程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次

#include <iostream>
using namespace std;

//对象的初始化和清理

class Person {
	public:
		//1、构造函数,进行对象的初始化
		//没有返回值,不用写void
		//构造函数的名字必须和类名相同
		//构造函数可以有参数,参数类型必须与类成员变量类型一致
		//构造函数可以重载,但不能有默认参数
		//创建对象时,系统自动调用构造函数进行初始化,且只调用一次
		Person() {
			cout << "Person() constructor called." << endl;
		}

		//2、析构函数,进行对象的清理
		//没有返回值,不用写void
		//析构函数的名字必须和类名相同,但在前面加上波浪符号“~”
		//析构函数不能有参数,不能重载
		//析构函数在对象销毁时自动调用,一般用来释放资源
		//系统自动调用析构函数进行清理,且只调用一次
		~Person() {
			cout << "~Person() destructor called." << endl;
		}
};
//构造和析构都是必须有的实现,如果我们自己不提供,编译器会提供一个空实现的默认构造函数和析构函数
void test_1() {
	//在栈上的数据,test_1执行完毕后,栈空间自动释放,不需要手动调用析构函数
	Person p1; //调用构造函数初始化对象
	
}

int main() {

	test_1();//调用test_1函数,创建对象p1,并调用构造函数初始化对象

	//Person p1; //调用构造函数初始化对象

	system("pause");
	return 0;
}
4.2.2 构造函数的分类及调用

两种分类方式:

  •         按参数分为:有参构造和无参构造
  •         按类型分为:普通构造和拷贝构造

三种调用方式:

  • 括号法
  • 显示法
  • 隐式转换法

代码示例:

#include <iostream>
using namespace std;

// 构造函数分类及调用

//分类
// 按照参数分类,无参构造(默认构造函数)、有参构造(参数构造函数)
// 按照类型分类,普通构造函数、拷贝构造函数
class Person {
	public:
		//构造函数
		Person() { cout << "Person()构造函数" << endl; } //默认构造函数
		Person(int a) { age = a; cout << "Person(int age)构造函数" << endl; } //有参构造函数

		//拷贝构造函数
		Person(const Person& p) { 
			age = p.age; //拷贝构造函数从参数对象拷贝数据到新对象
			cout << "Person(const Person& p)拷贝构造函数" << endl; 
		}

		~Person() { cout << "~Person()析构函数" << endl; } //析构函数

		int age;//成员变量
};

//调用
void test() {
	//1、括号法
	//Person p1; //调用默认构造函数
	//Person p2(18); //调用有参构造函数
	//Person p3(p2); //调用拷贝构造函数

	//注意事项
	//调用默认构造函数时,不要加括号(),Person p1(); 编译器会认为是声明了一个函数,不会认为在创建对象
	//调用有参构造函数时,必须传入参数
	//调用拷贝构造函数时,必须传入参数对象

	//cout << "p2年龄: " << p2.age << endl;//输出18
	//cout << "p3年龄: " << p3.age << endl;//输出18

	//2、显示法
	//Person p1;//调用默认构造函数
	//Person p2 = Person(20); //调用有参构造函数
	//Person p3 = p2; //调用拷贝构造函数

	//Person(20);//匿名对象,特点:当前执行结束后,系统立即回收

	//注意事项
	//不要利用拷贝构造函数 初始化匿名对象;编译器会认为 Person p3 == Person p3; 对象声明,重定义

	//cout << "显示法,p2年龄: " << p2.age << endl;//输出20
	//cout << "显示法,p3年龄: " << p3.age << endl;//输出20
	
	//3、隐式转换法
	Person p4 = 25; //调用有参构造函数,隐式转换为Person(int age);相当于Person p4 = Person(25);
	Person p5 = p4; //调用拷贝构造函数,隐式转换为Person(const Person& p);相当于Person p5 = Person(p4);
	cout << "隐式转换法,p4年龄: " << p4.age << endl;//输出25
}

int main() {
	test();

	return 0;
}
4.2.3 拷贝构造函数调用时机

C++中拷贝构造函数调用时机通常有三种情况

  • 使用一个已经创建完毕的对象来初始化一个新对象
  • 值传递的方式给函数参数传值
  • 以值方式返回局部对象

代码示例:

#include <iostream>
using namespace std;

//拷贝构造函数调用时机

class Person{
    public:
        Person() {
            cout<<"Person() 默认构造函数调用"<<endl;
        }
        Person(int age){
            cout<<"Person(int age) 有参构造函数调用"<<endl;
            m_age = age;
        }
        Person(const Person& p){
            cout<<"Person(const Person& p) 拷贝构造函数调用"<<endl;
            m_age = p.m_age;
        }
        ~Person(){
            cout<<"~Person() 析构函数调用"<<endl;
        }
    //private:
        int m_age;
};
//1、使用一个已经创建完毕的对象去初始化另一个对象
void test_1(){
    Person p1(20);//调用有参构造函数
    Person p2(p1); //调用拷贝构造函数
    cout<<"p2.m_age年龄  = "<<p2.m_age<<endl;
}
//2、值传递的方式给函数参数传值
void test_2(Person p){
    
}
void test_3(){
    Person p;//局部对象,调用默认构造函数
    test_2(p); //值传递方式给函数参数传值,调用拷贝构造函数
}
//3、值方式返回局部对象
Person test_4(){
    Person p1; //局部对象,调用默认构造函数
    cout<<(int*)&p1<<endl; //输出地址
    return p1; //值方式返回局部对象,调用拷贝构造函数
}
void test_5(){
    Person p = test_4(); //值方式返回局部对象,调用拷贝构造函数
    cout<< (int*)&p << endl; //输出地址
}

int main(){
    test_1();//输出:Person(int age) 有参构造函数调用 Person(const Person& p) 拷贝构造函数调用

    test_3();//输出:Person() 默认构造函数调用 Person(const Person& p) 拷贝构造函数调用

    test_5();//输出:Person() 默认构造函数调用 Person(const Person& p) 拷贝构造函数调用 Person(const Person& p) 拷贝构造函数调用 p.m_age年龄  = 0

    return 0;
}
4.2.4 构造函数调用规则

默认情况下,C++编译器至少给一个类添加3个函数

  • 1.默认构造函数(无参,函数体为空)
  • 2.默认析构函数(无参,函数体为空)
  • 3.默认拷贝构造函数,对属性进行值拷贝

构造函数调用规则如下

  • 如果用户定义有参构造函数,C++不在提供默认无参构造,但是会提供默认拷贝构造
  • 如果用户定义拷贝构造函数,C++不会再提供其他构造函数

代码示例:

#include <iostream>
using namespace std;

// 构造函数调用规则
//1、创建一个类,C++编译器给一个类添加3个函数
//默认构造函数(空实现)
//拷贝构造函数(值拷贝)
//析构函数(空实现)

//2、如果我们写了有参构造函数,那么编译器不会再提供默认构造函数,依然提供拷贝构造函数;
//2、如果我们写了拷贝构造函数,那么编译器不会再提供构造函数,

class Person {
    public:
         构造函数
        //Person() {
        //    cout << "Person default constructor called. 默认构造函数调用" << endl;
        //}
        // 构造函数
        Person(int age) {
            cout << "Person constructor with age called.  带参数的构造函数调用" << endl;
            AGE = age;
        }
        // 拷贝构造函数
        Person(const Person& p) {
            cout << "Person copy constructor called.  拷贝构造函数调用" << endl;
            AGE = p.AGE;// 值拷贝
        }
        ~Person() {
            cout << "Person destructor called.  析构函数调用" << endl;
        }
        // 成员变量
        int AGE;
};
//void test_1() {
//    Person p;  // 调用默认构造函数
//    p.AGE = 18;  // 给对象成员变量赋值
//    Person p2(p);  // 调用拷贝构造函数
//    cout<<"p2的年龄是:"<<p2.AGE<<endl;
//}
void test_2() {
    Person p(20);  // 调用带参数的构造函数
    Person p2(p);  // 调用拷贝构造函数
    cout<<"p2的年龄是:"<<p2.AGE<<endl;
}

int main() {
    //test_1();//输出:Person default constructor called. 默认构造函数调用
              //Person constructor with age called.  带参数的构造函数调用
              //Person copy constructor called.  拷贝构造函数调用
              //p2的年龄是:18
              //Person destructor called.  析构函数调用
              //Person destructor called.  析构函数调用
    test_2();//输出:Person constructor with age called.  带参数的构造函数调用
              //Person copy constructor called.  拷贝构造函数调用
              //p2的年龄是:20
              //Person destructor called.  析构函数调用
              //Person destructor called.  析构函数调用

    return 0;
}
4.2.5 深拷贝与浅拷贝

深浅拷贝是面试经典问题,也是常见的一个坑
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作
代码示例:

4.2.6 初始化列表

作用:
C++提供了初始化列表语法,用来初始化属性
语法:构造函数(): 属性1(值1),属性2(值2)...{}
代码示例: 

#include <iostream>
using namespace std;

//初始化列表

class Person {
	public:
		传统方式初始化
		//Person(int a, int b, int c) {
		//	age = a;
		//	hei = b;
		//	wei = c;
		//}
		//初始化列表方式初始化
		Person(int a, int b, int c) : age(a), hei(b), wei(c) {}
		void print() {
			cout << "age: " << age << endl;
			cout << "hei: " << hei << endl;
			cout << "wei: " << wei << endl;
		}
	private:
		int age;
		int hei;
		int wei;
};

int main() {
	Person p1(1, 2, 3);
	p1.print();
	return 0;
}
4.2.7 类对象作为类成员

C++类中的成员可以是另一个类的对象,我们称该成员为 对象成员
代码示例

class A {}
class B
{
    A a;
}


B类中有对象A作为成员,A为对象成员
那么当创建B对象时,A有B的构造和析构的顺序是谁先谁后?
代码示例:

#include <iostream>
#include <string>
using namespace std;

// 类对象作为类成员

//手机类
class Phone {
	public:
		Phone(string pName) {
			cout << "Phone 类对象初始化" << endl;
			PName = pName;
		}
		~Phone() {
			cout << "Phone 类对象清理" << endl;
		}
		string PName;
};

//人类
class Person {
	public:
		//
		Person(string name, string pName) : Name(name), Phone(pName) {//
			cout << "Person 类对象初始化" << endl;
		}
		~Person() {
			cout << "Person 类对象清理" << endl;
		}
		string Name; // 成员变量初始化
		Phone Phone; // 类对象初始化
};

//当其他类对象作为本类成员,构造时候先构造类对象,再构造自身,析构的顺序与构造相反

void test() {
	Person p("Tom", "iPhone 11");
	cout << p.Name << "的手机是:" << p.Phone.PName << endl;// 输出:Person 类对象初始化Tom的手机是:iPhone 11
}

int main() {
	test();// 输出:Person 类对象初始化Phone 类对象初始化Tom的手机是:iPhone 11Phone 类对象清理Person 类对象清理
	
	return 0;
}
4.2.8 静态成员 

静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员
静态成员分为:

  • 静态成员变量

        所有对象共享同一份数据
        在编译阶段分配内存
         类内声明,类外初始化

  • 静态成员函数

        所有对象共享同一个函数
        静态成员函数只能访问静态成员变量

示例1:静态成员变量
#include <iostream>
using namespace std;

// 静态成员变量
class Person {
	public:
		//1、类中所有对象共享同一个变量
		//2、编译阶段分配内存,运行时初始化
		//3、只能在类内部声明,不能在类外定义;类外初始化操作
		static int count; // 静态成员变量,

		//静态成员变量也是有访问权限的
	private:
		static int age; // 静态成员变量,
};

int Person::count = 10; // 静态成员变量初始化, 类外初始化操作
int Person::age = 100; // 静态成员变量初始化, 类外初始化操作

void test() {
	Person p; 
	cout << "Person count: " << p.count << endl;// 输出10

	Person p1;
	p1.count = 20; // 静态成员变量赋值,类外初始化操作
	cout << "Person count: " << p1.count << endl;// 输出20
}
void test1() {
	// 静态成员变量,不属于某个对象,而是属于类本身,所有对象共享同一个变量
	//因此静态变量 有两种访问方式:
	//1、通过类名访问,如 Person::count
	cout << "通过类名访问Person count: " << Person::count << endl;// 输出20

	//cout << "通过对象访问Person age: " << Person::age << endl;// 错误,静态成员变量不能通过对象访问

	//2、通过对象访问,如 p.count
	Person p2;
	cout << "对象访问Person count: " << p2.count << endl;// 输出20
}

int main() {
	test(); // 输出10 20

	test1(); // 输出

	system("pause");
	return 0;
}
示例2:静态成员函数
#include <iostream>
using namespace std;

// 静态成员函数
// 静态成员函数只能访问静态成员变量
// 所有对象共享同一份静态成员函数

class MyClass {
    public:
        // 静态成员函数
        static void function() {
            count = 100;// 静态成员函数可以访问静态成员变量
            //num = 200; // 错误,静态成员函数不能访问非静态成员变量;无法区分
            cout << "This is a static member function" << endl;
        }

        static int count; // 静态成员变量
        int num; // 非静态成员变量

        //静态成员函数访问权限
    private:
        static void privateFunction() {
            cout << "This is a private static member function" << endl;
        }
};

int MyClass::count = 0; // 静态成员变量初始化

// 调用静态成员函数,两种方式
void test() {
    //1、通过对象调用静态成员函数
    MyClass obj;
    obj.function();
    //2、通过类名调用静态成员函数
    MyClass::function();

    //MyClass::privateFunction(); // 错误,无法调用私有静态成员函数
}

int main() {
    test();

    return 0;
}
举报

相关推荐

0 条评论