❀C++特殊类
前言:在C++这片浩瀚的编程海洋中,基础语法与常用库如同岛屿与浅滩,引领着每一位初学者逐步前行。然而,当我们的航程逐渐深入,便会发现那些隐藏于波涛之下的特殊类,它们如同深海中的宝藏,等待着勇敢的探索者去发掘
现在我将带领大家一同踏上这场探索之旅,通过详细解析C++中的特殊类,揭示它们的设计原理、应用场景以及使用技巧。我们将从基础概念出发,逐步深入到高级特性,通过实例演示和代码分析,帮助读者逐步掌握这些特殊类的精髓
让我们一同揭开C++特殊类的神秘面纱,领略其独特的魅力与力量吧!
📒1. 不能被拷贝的类
实现方式:
C++98
:将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可
C++11
:C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数
代码示例 (C++):
//不能被拷贝的类
//C++98
class CopyBan
{
// ...
private:
CopyBan(const CopyBan&);
CopyBan& operator=(const CopyBan&);
//...
};
//C++11
class CopyBan
{
// ...
CopyBan(const CopyBan&) = delete;
CopyBan& operator=(const CopyBan&) = delete;
//...
};
📙2. 只能在堆上创建对象
实现方式:
方案一:析构函数私有化:
代码示例 (C++):
//只能在堆上创建对象
class HeapOnly
{
public:
// 对象的销毁
/*static void Destroy(HeapOnly* ptr)
{
delete ptr;
}*/
// 对象的销毁
void Destroy()
{
delete this;
}
private:
~HeapOnly()
{
cout << "~HeapOnly()" << endl;
}
};
int main()
{
HeapOnly* ptr = new HeapOnly;
//HeapOnly::Destroy(ptr);
ptr->Destroy();
return 0;
}
方案二:构造函数私有化:
代码示例 (C++):
class HeapOnly
{
public:
// 静态的成员函数,完成完成堆对象的创建
static HeapOnly* CreateObj()
{
return new HeapOnly;
}
private:
HeapOnly()
{
cout << "HeapOnly()" << endl;
}
// 防止别人调用拷贝在栈上生成对象
//C++98
HeapOnly(const HeapOnly& copy);
//C++11
HeapOnly(const HeapOnly& copy) = delete;
};
int main()
{
HeapOnly* ptr = HeapOnly::CreateObj();
//HeapOnly copy(*ptr);
return 0;
}
📚3. 只能在栈上创建对象
实现方式:
思考一下:这里的实现方法和上面似乎有点相同,但是我们在实现时,是否也要像上面一样delete掉拷贝构造呢?
静态成员函数 -> 完成栈对象的创建:
static StackOnly CreateObj()
{
StackOnly obj;
return obj;
}
// 这里会让对象在堆上创建
StackOnly* ptr = new StackOnly(obj);
// 如果我们 delete 拷贝构造,会发现CreateObj()也会受到影响,所以我们只能另辟蹊径
// 我们要从 new 下手让我们不能用 new 来创建对象
实现专属的operator new
:
void* operator new(size_t size)
{
cout << "void* operator new(size_t size)" << endl;
return malloc(size);
}
代码示例 (C++):
// 只能在栈上创建的类
class StackOnly
{
public:
static StackOnly CreateObj()
{
StackOnly obj;
return obj;
}
// 如果我们将拷贝构造delete,那么我们就无法创建对象,因为在CreateObj()中也会发生拷贝构造
//StackOnly(const StackOnly& copy) = delete;
void* operator new(size_t size) = delete;
//实现专属的operator new
//当我们new这类对象时,我们会优先调用operator new,而不是全局(就近原则)
/*void* operator new(size_t size)
{
cout << "void* operator new(size_t size)" << endl;
return malloc(size);
}*/
private:
StackOnly()
{
cout << "StackOnly()" << endl;
}
};
int main()
{
StackOnly obj = StackOnly::CreateObj();
// 发生拷贝构造是会在堆上创建类,但是我们能不能将拷贝构造delete呢?
//StackOnly* ptr = new StackOnly(obj);
return 0;
}
📜4. 不能被继承的类
实现方式:
-
C++98
:中构造函数私有化,派生类中调不到基类的构造函数就无法继承 -
C++11
:一个类如果不希望被其他类继承,可以通过将其声明为final类来实现
代码示例 (C++):
// 不能被继承的类
//C++98
class A
{
public:
static A GetInstance()
{
return A();
}
private:
A()
{}
};
// 不能被继承的类
//C++11
class A final
{
// ....
};
📝5. 只能创建一个对象(单例模式)
🌞设计模式
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模
式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样
⭐单例模式
单例模式的核心在于控制实例的数目,节省系统资源,并允许全局访问
- 饿汉模式
提前创建好程序,启动时就创建一个唯一的实例对象 -> (提前做好)
优点
:实现简单
缺点
:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定
代码示例 (C++):
class A
{
public:
static A* GetInstance()
{
return &_inst;
}
void Add(const string& key, const string& value)
{
_dict[key] = value;
}
void Print()
{
for (auto& kv : _dict)
{
cout << kv.first << ":" << kv.second << endl;
}
}
private:
A() // 私有构造函数
{}
//限制类外随意创建对象
A(const A& copy) = delete;
A& operator=(const A& aa) = delete;
map<string, string> dict;
static A _inst;// 静态实例
};
// 类的外部定义静态实例
A A::_inst;
int main()
{
A::GetInstance()->Add("sort", "排序");
A::GetInstance()->Add("left", "左边");
A::GetInstance()->Add("right", "右边");
A::GetInstance()->Print();
return 0;
}
- 懒汉模式
第一次用的时候在创建 -> (现吃现做)
优点
:第一次使用实例对象时,创建对象,进程启动无负载。多个单例实例启动顺序自由控制
缺点
:复杂
代码示例 (C++):
class B
{
public:
static B* GetInstance()
{
// 第一次为空的时候,创建对象
if (_inst == nullptr)
{
_inst = new B;
}
return _inst;
}
void Add(const string& key, const string& value)
{
_dict[key] = value;
}
void Print()
{
for (auto& kv : _dict)
{
cout << kv.first << ":" << kv.second << endl;
}
}
static void DelInstance()
{
if (_inst)
{
delete _inst;
_inst = nullptr;
}
}
private:
B()
{}
//限制类外随意创建对象
B(const B& copy) = delete;
B& operator=(const B& bb) = delete;
map<string, string> _dict;
static B* _inst; // 指针的形式
class gc
{
public:
~gc()
{
DelInstance();
}
};
static gc _gc;
};
B* B::_inst = nullptr;
B::gc B::_gc;
int main()
{
B::GetInstance()->Add("sort", "排序");
B::GetInstance()->Add("left", "左边");
B::GetInstance()->Add("right", "右边");
B::GetInstance()->Print();
return 0;
}
懒汉模式并非这么简单,后面还要牵扯到线程安全,线程安全需要额外处理
📖6. 总结
随着我们一同探索了C++中特殊类的广阔天地,相信你已经对这些高级特性有了更深的理解与感悟。特殊类不仅是C++语言复杂性和强大功能的体现,更是编程艺术的结晶,它们以独特的方式解决了传统编程中难以处理的问题,提升了代码的效率、安全性和可维护性
用一句话总结一下就是:“掌握C++特殊类,就是掌握了一种强大的编程工具,它将助你在编程的世界里走得更远、更稳。”
愿你在未来的编程道路上,能够勇往直前、不断突破自我,创造出更多优秀的作品和成果!
希望本文能够为你提供有益的参考和启示,让我们一起在编程的道路上不断前行!
谢谢大家支持本篇到这里就结束了,祝大家天天开心!