14-C++ object-oriented (singleton mode, const member, shallow copy, deep copy)

singleton pattern

 

        Singleton mode: A type of design mode that ensures that only one object is always created for a certain class

  1.         Constructor\destructor privatization
  2.         Define a private static member variable pointing to the only singleton object (Rocket* m_rocket)
  3.         Provide a common interface for accessing singleton objects (shareRocket())

class Rocket {
private:
	static Rocket* m_rocket;
	Rocket() {}
public:
	static Rocket* shareRocket() {
		//注意考虑多线程安全问题
		if (m_rocket==NULL)
		{
			m_rocket = new Rocket();
		}
		return m_rocket;
	}
	void run() {
		cout << "run()" << endl;
	}
};
Rocket* Rocket::m_rocket = NULL;
int main() {
	Rocket* p = Rocket::shareRocket();
	Rocket* p1 = Rocket::shareRocket();
	Rocket* p2 = Rocket::shareRocket();
	Rocket* p3 = Rocket::shareRocket();
	cout << p << endl;
	cout << p1 << endl;
	cout << p2 << endl;
	cout << p3 << endl;
	p->run();
	return 0;
}

When you need to destroy the singleton object in the heap, you also need to write a public interface in the class

static void deleteRocket() {
        //需要考虑多线程问题
		if (m_rocket != NULL)
		{
			delete m_rocket;
			m_rocket = NULL;//不赋值NULL可以会成野指针。使得重新申请单例对象时出现错误                     
                            //if(m_rocket==NULL)会不成立
		}
	}

In order to prevent external direct delete p; instead of deleting through the interface deleteRocket(), it is recommended to privatize the destructor. The complete code is as follows:

#include<iostream>
using namespace std; 
/*
单例模式:设计模式的一种,保证某个类永远只创建一个对象
1、构造函数\析构函数私有化
2、定义一个私有的static成员变量指向唯一的那个单例对象
3、提供一个公共的访问单例对象的接口
*/

class Rocket {
private:
	static Rocket* m_rocket;
	Rocket() {}
	~Rocket(){}
public:
	static Rocket* shareRocket() {
		//注意考虑多线程安全问题
		if (m_rocket==NULL)
		{
			m_rocket = new Rocket();
		}
		return m_rocket;
	}
	static void deleteRocket() {
		if (m_rocket != NULL)
		{
			delete m_rocket;
			m_rocket = NULL;
		}
	}
	void run() {
		cout << "run()" << endl;
	}
};
Rocket* Rocket::m_rocket = NULL;
int main() {
	Rocket* p = Rocket::shareRocket();
	Rocket* p1 = Rocket::shareRocket();
	Rocket* p2 = Rocket::shareRocket();
	Rocket* p3 = Rocket::shareRocket();
	cout << p << endl;
	cout << p1 << endl;
	cout << p2 << endl;
	cout << p3 << endl;
	p->run();
	Rocket::deleteRocket();
	return 0;
}

const member

  const members: member variables modified by const, non-static member functions

const member variable

  1. Must be initialized (class internal initialization), you can directly initialize the assignment when declaring
  2. Non-static const member variables can also be initialized in the initialization list

const member function

  1. The const keyword is written after the parameter list, and the declaration and implementation of the function must have const
  2. Non-static member variables cannot be modified internally
  3. Only const member functions and static member functions can be called internally
  4. Non-const member functions can call const member functions
#include <iostream>
using namespace std;

class Car
{
	int m_price;
	void run() const {
		cout << "run()" << endl;
		m_price = 0;//error
	}
};
int main() {

	return 0;
}

 reference type member

  1. Reference type member variables must be initialized by i (regardless of the static case)
  2. Initialize directly when declaring
  3. Initialize via initializer list

copy constructor

  1. A copy constructor is a type of constructor
  2. When using an existing object to create a new object (similar to copying), the copy function of the new object will be called for initialization
#include <iostream>
using namespace std;
class Car {
	int m_price;
	int m_length;
public:
	Car(int price = 0, int length = 0) :m_price(price), m_length(length) {
		cout << "Car(int price = 0, int length = 0) :m_price(price)" << endl;
	}
	//拷贝构造函数
	Car(const Car& car):m_price(car.m_price),m_length(car.m_length) {
		cout << "const Car& car" << endl;
		}
	void display() {
		cout << "price=" << m_price << ",length=" << m_length << endl;
	}
};


int main() {
	Car car1;
	Car car2(100, 200);
	//拷贝构造函数,利用已经存在的car2对象创建了一个car3对象
	//car3初始化时会调用拷贝构造函数
	Car car3(car2);
	car3.display();

	return 0;
}

shallow copy, deep copy

The default copy provided by the compiler is a shallow copy (shallow copy)

  1. Copy the values ​​of all member variables in one object to another object
  2. If a member variable is a pointer, only the address value stored in the pointer will be copied, and the memory space pointed to by the pointer will not be copied
  3. May cause heap space to be freed many times

If you need to implement deep copy (deep copy), you need to customize the copy constructor

  1. Copy the memory space pointed to by the member variable of pointer type to the new memory space

The following example shows that the shallow copy causes the variables in the heap space to point to the stack space, which is not safe

#include<iostream>
using namespace std;
class Car {
	int m_price;
	char* m_name;
public:
	Car(int price = 0, char* name = NULL):m_price(price),m_name(name) {}
	void display() {
		cout << "price is " << m_price << ",name is " <<m_name<< endl;
	}
};
int main() {
	const char* name = "bmw";
	char name2[] = { 'b','m','w','\0' };
	cout << name2 << endl;
	cout << strlen(name) << endl;

	Car *car = new Car(100, name2);
	car->display();
	return 0;
}

Deep copy, along with the pointed memory space is also copied

#include<iostream>
using namespace std;
class Car {
	int m_price;
	char* m_name;
public:
	Car(int price = 0, const char* name = NULL) :m_price(price){
		if (name == NULL) return;
		//申请新的堆空间
		m_name = new char[strlen(name) + 1]{};
		//拷贝字符串数据到新的堆空间
		strcpy(m_name, name);
	}
	~Car() {
		if (m_name == NULL) return;
		delete m_name;
		m_name = NULL;
	}
	void display() {
		cout << "price is " << m_price << ",name is " << m_name << endl;
	}
};

int main() {
	const char* name = "bmw";
	char name2[] = { 'b','m','w','\0' };
	cout << name2 << endl;
	cout << strlen(name) << endl;

	Car* car = new Car(100, name);
	car->display();
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_56728342/article/details/129806269