【C++】特殊类设计(上)

简介: 【C++】特殊类设计(上)

1. 设计一个类,不能被拷贝


如果一个类不能被拷贝,那么只需要让类外面不能调用类的拷贝构造和赋值重载即可


1. C++98的实现方式

将类的构造函数和赋值重载只声明不实现,并且声明为private

因为不声明的编译器会默认生成public的拷贝构造和赋值重载,因此需要声明为private的

//设计一个类不能被拷贝
class NoCopy
{
public:
    NoCopy() {}
private:
    NoCopy(const NoCopy& obj);
    NoCopy& operator=(const NoCopy& obj);
};
void test1()
{
    NoCopy obj1;
    NoCopy obj2(obj1);
}

b03d137d3b8e73d47f487f1a72f1ea85.png


2. C++11的实现方式

C++11提供了新的关键字delete,用于表示禁用某个函数,那么此时我们只需要禁用拷贝构造和赋值重载即可

class NoCopy
{
public:
    NoCopy() {}
    NoCopy(const NoCopy& obj) = delete;
    NoCopy& operator=(const NoCopy& obj) = delete;
private:
};
void test1()
{
    NoCopy obj1;
    NoCopy obj2(obj1);
}

dd3067ab383823910811ff273df38729.png


2. 设计一个类,只能在堆上创建对象


要规定某个类的创建位置,那么自动生成的构造函数就不能再使用了,而是重新提供一个方法,用于创建对象,在这个方法内部进行一些限制即可为了保证这个类创建的对象全部都在堆上,所以需要将所有的构造函数全部封起来,然后重新提供一个函数用来创建对象即可

//设计一个只能在堆上创建对象的类
class HeapOnly
{
public:
    HeapOnly* CreateObj()
    {
        return new HeapOnly;
    }
private:
    HeapOnly() {}
};

但是这样会有一个问题:我们要怎么调用这个CreateObj函数呢?

这是一个先有鸡还是先有蛋的问题:我们得通过对象来调用类的成员函数,但是这里需要先调用成员函数来创建对象,所以这里要给CreateObj函数使用static修饰,让其可以通过类名访问(HeapOnly::CreateObj()

同时,我们还需要将拷贝构造给私有化,否则将会出现HeapOnly obj2 = *pobj;的情况,会构造一个obj2是在栈上的

所以最终的设计代码为:

//设计一个只能在堆上创建对象的类
class HeapOnly
{
public:
    static HeapOnly* CreateObj()
    {
        return new HeapOnly;
    }
private:
    HeapOnly() {}
    HeapOnly(const HeapOnly& obj) {};
};
void test()
{
    HeapOnly* pobj =  HeapOnly::CreateObj();
    HeapOnly obj2 = *pobj;
}


e864cc6a12db062d918c6d775320cada.png

当然,在C++11之后,我们可以使用delete关键字禁用拷贝构造函数


3. 设计一个类,只能在栈上创建对象


同样的,需要将默认构造函数私有化,然后重新提供一个方法,用于创建对象,在这个方法内部进行一些限制

//设计一个只能在栈上创建对象的类
class StackOnly
{
public:
    static StackOnly CreateObj()
    {
        return StackOnly();
    }
private:
    StackOnly() {}
};
void test()
{
    StackOnly obj1 = StackOnly::CreateObj();
}


这里能够禁用掉在堆上创建对象的方式,但是没有办法完全禁掉其他方式,这里可以使用static修饰对象,让其在静态区创建static StackOnly obj1 = StackOnly::CreateObj();

如果想禁止在静态区创建的话,这里可以考虑禁止拷贝构造

但是禁止了拷贝构造之后就不能使用StackOnly obj1 = StackOnly::CreateObj();这种方式调用构造对象了,因此,这个类我们是封不死的,最多只能限制不这样使用


4. 设计一个类不能被继承


4.1C++98的方式

构造函数私有化,所有派生类在构造对象的时候都会自动调用基类的构造函数,基类的构造函数被私有化之后派生类构造对象的时候无法自动调用。

class NonInherit
{
public:
    static NonInherit CreateObj()
    {
        return NonInherit();
    }
private:
    NonInherit() {}
};
class Derive : NonInherit
{
public:
private:
    int a;
};
void test1()
{
    Derive De;
}


7021b613afd50060a738e56f7d65adc1.png


4.2 C++11之后的方式

C++11新增了final关键字,final修饰类,表示该类不能被继承

class NonInherit final
{
};
class Derive : NonInherit
{
public:
private:
    int a;
};


ebafdacb2d4ce58bf837b170c85f07aa.png

相关文章
|
4天前
|
设计模式 安全 算法
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
14 0
|
5天前
|
C语言 C++
【C++】string类(常用接口)
【C++】string类(常用接口)
13 1
|
2天前
|
编译器 C++
【C++】继续学习 string类 吧
首先不得不说的是由于历史原因,string的接口多达130多个,简直冗杂… 所以学习过程中,我们只需要选取常用的,好用的来进行使用即可(有种垃圾堆里翻美食的感觉)
7 1
|
2天前
|
算法 安全 程序员
【C++】STL学习之旅——初识STL,认识string类
现在我正式开始学习STL,这让我期待好久了,一想到不用手撕链表,手搓堆栈,心里非常爽
10 0
|
2天前
|
存储 安全 测试技术
【C++】string学习 — 手搓string类项目
C++ 的 string 类是 C++ 标准库中提供的一个用于处理字符串的类。它在 C++ 的历史中扮演了重要的角色,为字符串处理提供了更加方便、高效的方法。
12 0
【C++】string学习 — 手搓string类项目
|
3天前
|
Java C++ Python
【C++从练气到飞升】06---重识类和对象(二)
【C++从练气到飞升】06---重识类和对象(二)
|
3天前
|
编译器 C++
【C++从练气到飞升】06---重识类和对象(一)
【C++从练气到飞升】06---重识类和对象(一)
|
3天前
|
存储 编译器 C语言
【C++从练气到飞升】02---初识类与对象
【C++从练气到飞升】02---初识类与对象
|
4天前
|
设计模式 算法 编译器
【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
9 0
|
4天前
|
算法 安全 调度
【C++入门到精通】 线程库 | thread类 C++11 [ C++入门 ]
【C++入门到精通】 线程库 | thread类 C++11 [ C++入门 ]
14 1