C++把类的设计看成类型设计

简介: C++把类的设计看成类型设计

1.类设计的建议


C++和其它面向对象的语言一样,,定义一个类就定义了一个新的类型。重载函数和操作符,内存的分配与释放,对象的构造与析构,全部掌握在你的手上。所以在设计类的时候,要像语言的设计者设计内置类型一样小心。


好的类型拥有自然的语法,直观的语义和高效率的实现。如何高效地设计一个类呢? 以下的问题在几乎所有的类型设计中都会遇到,以及考虑这些问题会如何影响到你的设计:


(1) 新类型的对象要如何创建和销毁?


这决定了要如何写构造函数和析构函数,包括要使用什么内存分配和释放函数,即new还是new[],delete还是delete[]。请参见前面的文章C++要成对使用new和delete且采取相同形式


(2) 对象的初始化和对象的赋值应该有何差别?


这决定了你如何写,如何区别构造函数和赋值运算符,以及不要把初始化与赋值混淆,因为它们的语义不同,构造函数适用于未创建的对象,赋值适用于已创建的对象,这也是为什么我们要在构造函数中使用初始化列表而不使用赋值的原因。请参见前面的文章确定对象使用前已先被初始化C++中要完整拷贝对象


(3) 新类型的对象如果以传值方式传递,意味着什么?


要记住拷贝构造函数决定了你的类型是如何被传值的,因为传值会生成本地的拷贝。


(4) 什么是新类型的合法值?


通常情况下,并不是成员的任何数值组合都是合法的。要让数据成员合法,我们需要根据合法的组合,在成员函数中对数值进行检测,尤其是构造函数,赋值运算符和setter。这也会影响到使用它的函数会抛出什么异常。


(5) 新类型属于某个继承层级吗?


如果你的新类型继承自某个已有的类,你的设计将被这些父类影响到,尤其是父类的某些函数是不是虚函数。如果你的新类型要作为一个父类,你将要决定把哪些函数声明为虚函数,尤其要注意析构函数。具体请参见前面的文章C++中为多态基类声明虚析构函数


(6) 新类型允许进行什么样的转换?


新类型的对象将会在程序的海洋中与其它各种各样的类型并用,这时你就要决定是否允许类型的转换。如果你希望把T1隐式转换为T2,你可以在T1中定义一个转换函数,例如operator T2,或者在T2中定义一个兼容T1的不加explicit修饰的构造函数。如果希望使用显式转换,你要定义执行显示转换的函数。请参见前面的文章C++在资源管理类中提供对原始资源的访问


(7) 什么样的运算符和函数对新类型是有意义的?


这决定了你要声明哪些函数,包括成员函数,非成员函数,友元函数等。


(8) 禁止哪些标准函数?


如果不希望使用编译器会自动生成的标准函数,把它们声明为私有。请参见前面的文章如果不想使用编译器默认生成的函数,请明确拒绝它!


(9) 谁该取用新类型的成员?


这影响到哪些成员是公有的(public),哪些是保护的

(protected),哪些是私有的(private)。这也能帮你决定哪些类和函数是友元的,以及要不要使用嵌套类(nested class)。


(10) 新类型的隐藏接口是什么?


新类型对于性能,异常安全性,资源管理(例如锁和内存)有什么保障? 哪些问题是自动解决不需要用户操心的? 要实现这些保障,自然会对这个类的实现产生限制,例如要使用智能指针而不要使用裸指针。


(11) 新类型的通用性


如果想让你的新类型通用于许多类型,定义一个类模板(class template),而不是单个新类型。


(12) 新类型真的是你所需要的吗?


如果你想定义一个子类只是为了给基类增加某些新功能,定义一些非成员的函数或者函数模板更加划算。


2.总结



(1) 类的设计犹如类型的设计。在定义一个新类型之前,请确定你已经考虑过上面所讨论的全部建议。

相关文章
|
1天前
|
编译器 C++
C++ 类构造函数初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。
41 30
|
15天前
|
存储 编译器 C++
C ++初阶:类和对象(中)
C ++初阶:类和对象(中)
|
15天前
|
C++
C++(十六)类之间转化
在C++中,类之间的转换可以通过转换构造函数和操作符函数实现。转换构造函数是一种单参数构造函数,用于将其他类型转换为本类类型。为了防止不必要的隐式转换,可以使用`explicit`关键字来禁止这种自动转换。此外,还可以通过定义`operator`函数来进行类型转换,该函数无参数且无返回值。下面展示了如何使用这两种方式实现自定义类型的相互转换,并通过示例代码说明了`explicit`关键字的作用。
|
15天前
|
存储 设计模式 编译器
C++(十三) 类的扩展
本文详细介绍了C++中类的各种扩展特性,包括类成员存储、`sizeof`操作符的应用、类成员函数的存储方式及其背后的`this`指针机制。此外,还探讨了`const`修饰符在成员变量和函数中的作用,以及如何通过`static`关键字实现类中的资源共享。文章还介绍了单例模式的设计思路,并讨论了指向类成员(数据成员和函数成员)的指针的使用方法。最后,还讲解了指向静态成员的指针的相关概念和应用示例。通过这些内容,帮助读者更好地理解和掌握C++面向对象编程的核心概念和技术细节。
|
28天前
|
存储 算法 编译器
c++--类(上)
c++--类(上)
|
1月前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
1月前
|
编译器 C++
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
|
15天前
|
存储 C++
C++(五)String 字符串类
本文档详细介绍了C++中的`string`类,包括定义、初始化、字符串比较及数值与字符串之间的转换方法。`string`类简化了字符串处理,提供了丰富的功能如字符串查找、比较、拼接和替换等。文档通过示例代码展示了如何使用这些功能,并介绍了如何将数值转换为字符串以及反之亦然的方法。此外,还展示了如何使用`string`数组存储和遍历多个字符串。
|
15天前
|
安全 程序员 C语言
C++(四)类型强转
本文详细介绍了C++中的四种类型强制转换:`static_cast`、`reinterpret_cast`、`const_cast`和`dynamic_cast`。每种转换都有其特定用途和适用场景,如`static_cast`用于相关类型间的显式转换,`reinterpret_cast`用于低层内存布局操作,`const_cast`用于添加或移除`const`限定符,而`dynamic_cast`则用于运行时的类型检查和转换。通过具体示例展示了如何正确使用这四种转换操作符,帮助开发者更好地理解和掌握C++中的类型转换机制。
|
21天前
|
C++
使用 QML 类型系统注册 C++ 类型
使用 QML 类型系统注册 C++ 类型
22 0